1. 概述
Singleton Pattren 要求一個類有且僅有一個實例,並且提供一個全局變量。這個創建的對象是獨一無二的,在這個單獨對象實例中,集中所創建類的所有屬性和方法。
在創建一個單例,何時需要,這是程序設計的關鍵。從定義上可知這個類供全局調用,產品(程序)都可調用,所有是個全局靜態變量,一般是不允許有派生類的。比如,火車的票數及票種,必須全局變量,這個往往是爲了防止多線程調用時,導致問題溢出。
2. 模型圖及思路
3. 代碼實現
//單例模式類不能派生
public sealed class Singleton
{
//靜態對象,才能在靜態函數中訪問
private static Singleton uniqueInstance;
//線程安全控制實例
static object synobj = new object();
public static Singleton GetInstace()
{
//不加線程控制時,當兩個線程同時運行GetInstance方法時,此時兩個線程判斷(uniqueInstance ==null)這個條件時都返回真,此時兩個線程就都會創建Singleton的實例
// 當第一個線程運行到這裏時,此時會對locker對象 "加鎖",
// 當第二個線程運行該方法時,首先檢測到locker對象爲"加鎖"狀態,該線程就會掛起等待第一個線程解鎖
// lock語句運行完之後(即線程運行完之後)會對該對象"解鎖"
lock(synobj)
{
// 如果類的實例不存在則創建,否則直接返回
//爲創建實例時,進行創建
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
return uniqueInstance;
}
//私有構造函數,只允許在此類中創建對象
private Singleton()
{
}
}
以上的設計確實解決多線程的問題,但是上面的代碼對於每個線程輔助對象locker枷鎖後,在判斷實例時候存在,對於這個操作完全沒必要。可以當地一個線程創建實例後,後面的線程只需要直接判斷是否爲null。就如一下的代碼。
//單例模式類不能派生
public sealed class Singleton
{
//靜態對象,才能在靜態函數中訪問
private static Singleton uniqueInstance;
//線程安全控制實例
static object synobj = new object();
public static Singleton GetInstace()
{
//不加線程控制時,當兩個線程同時運行GetInstance方法時,此時兩個線程判斷(uniqueInstance ==null)這個條件時都返回真,此時兩個線程就都會創建Singleton的實例
// 當第一個線程運行到這裏時,此時會對locker對象 "加鎖",
// 當第二個線程運行該方法時,首先檢測到locker對象爲"加鎖"狀態,該線程就會掛起等待第一個線程解鎖
// lock語句運行完之後(即線程運行完之後)會對該對象"解鎖"
//只需要家這句判斷就可以了
if(uniqueInstance == null)
{
lock(synobj)
{
// 如果類的實例不存在則創建,否則直接返回
//爲創建實例時,進行創建
if (uniqueInstance == null)
{
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
//私有構造函數,只允許在此類中創建對象
private Singleton()
{
}
}
public sealed class Singleton
2{
3 static readonly Singleton instance=new Singleton();
4
5 static Singleton()
6 {
7 }
8
9 Singleton()
10 {
11 }
12
13 public static Singleton Instance
14 {
15 get
16 {
17 return instance;
18 }
19 }
20 }
21
看到上面這段富有戲劇性的代碼,我們可能會產生懷疑,這還是Singleton模式嗎?在此實現中,將在第一次引用類的任何成員時創建實例。公共語言運行庫負責處理變量初始化。該類標記爲 sealed 以阻止發生派生,而派生可能會增加實例。此外,變量標記爲 readonly,這意味着只能在靜態初始化期間(此處顯示的示例)或在類構造函數中分配變量。
該實現與前面的示例類似,不同之處在於它依賴公共語言運行庫來初始化變量。它仍然可以用來解決 Singleton 模式試圖解決的兩個基本問題:全局訪問和實例化控制。公共靜態屬性爲訪問實例提供了一個全局訪問點。此外,由於構造函數是私有的,因此不能在類本身以外實例化 Singleton 類;因此,變量引用的是可以在系統中存在的唯一的實例。
由於 Singleton 實例被私有靜態成員變量引用,因此在類首次被對 Instance 屬性的調用所引用之前,不會發生實例化。
4.要點知識
- Singleton模式是限制而不是創建。
- Singleton類中實例可以設置爲Protected供子類派生
- Singleton考慮了對象創建的管理,沒有進行銷燬,就支持垃圾回收的平臺,就不用對銷燬進行管理。
- 優點:阻止其他對象實例化自己的副本,保證所有對象訪問的唯一實例。
- 缺點:使用Singleton模式時,開發人員不能有new,進行實例化。