意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例是通过子例化可扩展的,并且客户应该无需要更改代码就能使用一个扩展的实例时。
实现:
1. 私有的构造函数防止在外部实例化。
2. 保存唯一实例的静态的私有变量。
3. 初始化并获得唯一实例的静态方法。
●简单实现:
优点:可以使用附加功能(例如,对子类进行实例化)
惰性实例化,避免应用程序启动时实例化不必要的Singleton实例。
缺点:多线程的环境下将得到Singleton的多个实例
Private Shared me_instance As Singleton = Nothing
Private Sub New()Sub New()
End Sub
Public ReadOnly Shared Property Instance()Property Instance()
Get
If me_instance Is Nothing Then
me_instance = New Singleton()
End If
Return me_instance
End Get
End Property
End Class
●安全的线程:
优点:可多线程访问。
缺点:增加了额外的开销,损失了性能。
Private Shared me_instance As Singleton = Nothing
Private Shared syncObject As Object = New Object
Private Sub New()Sub New()Sub New()Sub New()
End Sub
Public ReadOnly Shared Property Instance()Property Instance()
Get
SyncLock syncObject
If me_instance Is Nothing Then
me_instance = New Singleton()
End If
Return me_instance
End SyncLock
End Get
End Property
End Class
●双重锁定:
优点:解决了线程并发的问题避免在每个Instance属性方法的调用中都出现独占锁定。可以为构造函数添加参数。
缺点:无法实现延迟初始化。
Private Shared _instance As Singleton
Private Shared syncObject As Object = New Object 'Lock synchronization object
Protected Sub New()Sub New()
End Sub
Public Shared ReadOnly Property Instance()Property Instance()
Get
If _instance Is Nothing Then
SyncLock syncObject
If _instance Is Nothing Then
_instance = New Singleton
End If
End SyncLock
End If
Return _instance
End Get
End Property
End Class
●静态初始化:
优点:第一次引用类的成员时创建实例。标记为sealed(NotInheritable)阻止变量标记为ReadOnly,只能在静态初始化期间或在类构造函数中分配变量
缺点:对实例化控制权较少
注释:实现Singleton的首选方法
Public Shared ReadOnly Instance As New Singleton
Protected Sub New()Sub New()Sub New()Sub New()
End Sub
End Class
●延迟初始化:
优点:初始化工作由静态成员(Nested类)来完成
Protected Sub New()Sub New()
End Sub
Public Shared ReadOnly Property Instance()Property Instance()
Get
Return Nested.instance
End Get
End Property
Private Class NestedClass Nested
Shared Sub New()Sub New()Sub New()Sub New()
End Sub
Friend Shared ReadOnly instance As New Singleton
End Class
End Class
实例:
' Singleton pattern -- Real World example
Imports System
Imports System.Collections
Imports System.Threading
Namespace DoFactoryNamespace DoFactory.GangOfFour.Singleton.RealWorld
' MainApp test application
Class MainAppClass MainApp
Private Shared Sub Main()Sub Main()
Dim b1 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b2 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b3 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b4 As LoadBalancer = LoadBalancer.GetLoadBalancer()
'Same instance?
If b1 = b2 AndAlso b2 = b3 AndAlso b3 = b4 Then
Console.WriteLine("Same instance" & Chr(10) & "")
End If
For i As Integer = 0 To 14
'All are the same instance -- use b1 arbitrarily
'Load balance 15 server requests
Console.WriteLine(b1.Server)
Next
'Wait for user
Console.Read()
End Sub
End Class
' "Singleton"
Class LoadBalancerClass LoadBalancer
Private Shared instance As LoadBalancer
Private servers As New ArrayList()
Private random As New Random()
'Lock synchronization object
Private Shared [syncLock] As New Object()
'Constructor (protected)
Protected Sub New()Sub New()
' List of available servers
servers.Add("ServerI")
servers.Add("ServerII")
servers.Add("ServerIII")
servers.Add("ServerIV")
servers.Add("ServerV")
End Sub
Public Shared Function GetLoadBalancer()Function GetLoadBalancer() As LoadBalancer
'Support multithreaded applications through
' 'Double checked locking' pattern which (once
' the instance exists) avoids locking each
' time the method is invoked
If instance Is Nothing Then
SyncLock [syncLock]
If instance Is Nothing Then
instance = New LoadBalancer()
End If
End SyncLock
End If
Return instance
End Function
'Simple, but effective random load balancer
Public ReadOnly Property Server()Property Server() As String
Get
Dim r As Integer = random.[Next](servers.Count)
Return servers(r).ToString()
End Get
End Property
End Class
End Namespace
' Singleton pattern -- Real World example
Imports System
Imports System.Collections
Namespace DoFactoryNamespace DoFactory.GangOfFour.Singleton.NETOptimized
'MainApp test application
Class MainAppClass MainApp
Private Shared Sub Main()Sub Main()
Dim b1 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b2 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b3 As LoadBalancer = LoadBalancer.GetLoadBalancer()
Dim b4 As LoadBalancer = LoadBalancer.GetLoadBalancer()
'Confirm these are the same instance
If b1 is b2 AndAlso b2 is b3 AndAlso b3 is b4 Then
Console.WriteLine("Same instance" & Chr(10) & "")
End If
For i As Integer = 0 To 14
'All are the same instance -- use b1 arbitrarily
'Load balance 15 requests for a server
Console.WriteLine(b1.Server)
Next
'Wait for user
Console.Read()
End Sub
End Class
' Singleton
NotInheritable Class LoadBalancerClass LoadBalancer
'Static members are lazily initialized.
' .NET guarantees thread safety for static initialization
Private Shared ReadOnly instance As New LoadBalancer()
Private servers As New ArrayList()
Private random As New Random()
'Note: constructor is private.
Private Sub New()Sub New()
'List of available servers
servers.Add("ServerI")
servers.Add("ServerII")
servers.Add("ServerIII")
servers.Add("ServerIV")
servers.Add("ServerV")
End Sub
Public Shared Function GetLoadBalancer()Function GetLoadBalancer() As LoadBalancer
Return instance
End Function
'Simple, but effective load balancer
Public ReadOnly Property Server()Property Server() As String
Get
Dim r As Integer = random.[Next](servers.Count)
Return servers(r).ToString()
End Get
End Property
End Class
End Namespace
我对单件模式的理解:
1.封装全局变量
2.保证线程安全
参考资料:
《C#面向对象设计模式纵横谈系列课程(2)》 李建中老师
《.Net设计模式(2):单件模式(Singleton Pattern)》 Terrylee老师