1、簡單實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public sealed class Singleton
{
static Singleton instance = null;
public void Show()
{
Console.WriteLine( "instance function");
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
|
評注:
對於線程來說不安全
單線程中已滿足要求
優點:
由於實例是在 Instance 屬性方法內部創建的,因此類可以使用附加功能
直到對象要求產生一個實例才執行實例化;這種方法稱為“惰性實例化”。惰性實例化避免了在應用程序啟動時實例化不必要的 singleton。
2、線程的安全
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public sealed class Singleton
{
static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
return instance;
}
}
}
|
評注:
同一個時刻加了鎖的那部分程序只有一個線程可以進入
對象實例由最先進入的那個線程創建
后來的線程在進入時(instence == null)為假,不會再去創建對象實例
增加了額外的開銷,損失了性能
3、雙重鎖定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public sealed class Singleton
{
static Singleton instance = null;
private static readonly object padlock = new object();
private Singleton()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
|
評注:
多線程安全
線程不是每次都加鎖
允許實例化延遲到第一次訪問對象時發生
4、靜態初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public sealed class Singleton
{
private static readonly Singleton instance = null;
static Singleton()
{
instance = new Singleton();
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
|
評注:
依賴公共語言運行庫負責處理變量初始化
公共靜態屬性為訪問實例提供了一個全局訪問點
對實例化機制的控制權較少(.NET代為實現)
靜態初始化是在 .NET 中實現 Singleton 的首選方法
小注:
靜態構造函數既沒有訪問修飾符,C#會自動把他們標記為private,之所以必須標記為private,是為了阻止開發人員寫的代碼調用它,對它的調用總是由CLR負責的。
5、延遲初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public sealed class Singleton
{
private Singleton()
{
}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
public static void Hello()
{
}
private class Nested
{
internal static readonly Singleton instance = null;
static Nested()
{
instance = new Singleton();
}
}
}
|
評注:
初始化工作由Nested類的一個靜態成員來完成,這樣就實現了延遲初始化。
由於靜態函數的調用時機,是在類被實例化或者靜態成員被調用的時候進行調用,並且是由.net框架來調用靜態構造函數來初始化靜態成員變量,所以,如果按照寫法四來寫,再調用Hello方法的時候,就會實例化出來Singleton實例,這不是我們想看到的,因為我們有可能只是想用Hello方法,而不是別的。
注意事項:
1、Singleton模式中的實例構造器可以設置為protected以允許子類派生。
2、Singleton模式一般不要支持ICloneable接口,因為這可能會導致多個對象實例,與Singleton模式的初衷違背。
3、Singleton模式一般不要支持序列化,因為這也有可能導致多個對象實例,同樣與Singleton模式的初衷違背。
4、Singletom模式只考慮到了對象創建的管理,沒有考慮對象銷毀的管理。就支持垃圾回收的平台和對象的開銷來講,我們一般沒有必要對其銷毀進行特殊的管理。
總結:
1、Singleton模式是限制而不是改進類的創建。
2、理解和擴展Singleton模式的核心是“如何控制用戶使用new對一個類的構造器的任意調用”。
3、可以很簡單的修改一個Singleton,使它有少數幾個實例,這樣做是允許的而且是有意義的。