標籤:style class blog code http tar
一、簡介
單例模式主要用的作用是用於保證程式運行中某個類只有一個執行個體,並提供一個全域進入點。單例模式(Singleton)為GOF闡述的標準24種設計模式中最簡單的一個。但隨著時間推移,GOF所闡述的單例實現已不能完全滿足實際應用。
"ensure a class has only one instance, and provide a global point of access to it"
二、動機(應用情境)
幾乎在每個應用程式中,都需要有一個從中進行全域訪問和維護某種類型資料的地區。 在物件導向的 (OO) 系統中也有這種情況,在此類系統中,在任何給定時間只應運行一個類或某個類的一組預定義數量的執行個體。
1、當使用某個類來維護增量計數器時,此簡單的計數器類需要跟蹤在多個應用程式領域中使用的整數值。 此類需要能夠增加該計數器並返回當前的值。 對於這種情況,所需的類行為應該僅使用一個類執行個體來維護該整數,而不是使用其它類執行個體來維護該整數。
2、每台電腦可以有若干個印表機,但只能有一個Printer Spooler,避免兩個列印工作同時輸出到印表機。
3、PC機中可能有幾個串口,但只能有一個COM1口的執行個體。
4、系統中只能有一個視窗管理器。
5.NET Remoting中伺服器啟用物件中的Sigleton對象,確保所有的客戶程式的請求都只有一個執行個體來處理。
6.應用程式的日誌應用,一般都何用單例模式實現,這一般是由於共用的記錄檔一直處於開啟狀態,因為只能有一個執行個體去操作,否則內容不好追加。
三、C#實現
1、單線程實現
單線程單例模式實現/***單例模式的單線程實現。無法保證單線程模式下只產出唯一的一個執行個體。*/Class Singleton {private static Singleton Instance;//將建構函式定義為private防止該類在外部被執行個體化//如需有將此類定義可繼承的,則可將private更改為protectedprivate Singleton(){}public static Singleton GetInstance(){//當處於多線程環境時,可能存在多個線程在由於代碼執行的順序導致//多個線程產生多個執行個體,而違背該模式的初衷if(Instance==null){Instance=new Singleton();}return Instance;}}
可以說是一個標準的單例的代碼。
優點:
缺點:
多線程環境下它是不安全的。如果執行過程的不同線程同時進入 Instance 屬性方法,那麼可能會建立多個 Singleton 對象執行個體。每個線程都會執行下列語句,並決定必須建立新的執行個體。
2、多線程實現
多線程單例模式實現class Singleton { //volatile關鍵字。 這應該告訴編譯器不要對代碼重新排序,並且放棄最佳化。確保只有在執行個體變數分配完成後才能訪問執行個體變數。 //防止由於編譯器最佳化導致代碼控制失效. private static volatile Singleton instance; //使用 syncRoot 執行個體來進行鎖定(而不是鎖定類型本身),以避免發生死結。 private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { //雙重檢驗鎖定- Double-Check Locking // double-check locking 方法解決了線程並發問題,同時避免在每個 Instance 屬性方法的調用中都出現獨佔鎖定。 if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } }}
優點:由於執行個體的產生由自己控制,可以對非預設建構函式進行擴充、傳參等操作。
缺點:實現相對複雜
3、C#簡潔版
由於 C# 與公用語言運行庫也提供了一種"靜態初始化"方法,這種方法不需要開發人員顯式地編寫安全執行緒代碼,即可解決多線程建立等問題。
簡潔實現1public sealed class Singleton { //變數標記為 readonly,這意味著只能在靜態初始化期間(此處顯示的樣本)或在類建構函式中分配變數。 private static readonly Singleton instance = new Singleton(); private Singleton(){} public static Singleton Instance { get { return instance; } } }
更簡潔的方式:
簡潔實現1public sealed class Singleton { public static readonly Singleton Instance = new Singleton(); private Singleton(){} }
因為靜態建構函式是屬於類的,而不屬於任何一個執行個體,所以這個建構函式只會被執行一次,而且是在建立此類的第一個執行個體或引用任何靜態成員之前,由.NET自動調用。
1、由於靜態建構函式由.NET調用,所以不需要public和private等存取修飾詞。
2、在建立第一個類執行個體或任何靜態成員被引用時,.NET將自動調用靜態建構函式來初始化類。(我們無法調用,也不知道它何時被調用)
3、靜態建構函式屬於類,建構函式屬於執行個體,他們並不衝突。靜態建構函式只會運行一次。
缺點:由於在此解決方案中由 .NET Framework 負責執行初始化,無法在執行個體化之前使用非預設的建構函式或執行其他任務。在大多數情況下,靜態初始化是在.NET 中實現 Singleton 的首選方法。
四、總結
單線程版、多線程版、簡潔版有各自的應用,沒有那種實現是最好的。
總結上述三種實現方法,以是否需要在建立單例執行個體時傳參或執行其他任務分兩類。即:
1、不需要執行其他任務
使用簡潔版即可以保障在單線程、多線程都能安全使用的同時,代碼量較少。
2、需要
一般情況下,均為單線程版。則使用單線程建立。若程式有多線程應用則應用使用雙重檢測的多線程實現。
參考文檔:
http://msdn.microsoft.com/zh-cn/library/ff650316.aspx