1、模式分類
???? 1.1? 從目的來看:
??????????????????? ?????? – 創建型(Creational)模式:負責對象創建。
??????????????????? ?????? – 結構型(Structural)模式:處理類與對象間的組合。
?????????????????????????? – 行為型(Behavioral)模式:類與對象交互中的職責分配。
???? 1.2 從范圍來看:
????????????????????????? – 類模式處理類與子類的靜態關系。
??????????????????? ????? – 對象模式處理對象間的動態關系。
2、動機(Motivation)目的??
????????????????????在軟件系統中,經常有這樣一些特殊的類,必須保證它們在系統中只存在一個實例,才能確保它們的邏輯正確性、以及良好的效率。
3、意圖(Intent) ????????????
??????????????????? 保證一個類僅有一個實例,并提供一個該實例的全局訪問點。
????????????????????????????????????????????????????????????????????????????????????????? ——《設計模式》GoF
4、單例模式多種實現方法
??? 4.1 單線程Singleton 模式實現
1 class Singleton 2 { 3 private static Singleton instance; 4 private Singleton() //防止外界隨意new此對象,如果訪問級別設置成protected,那么子類可以派生,同時也也不可以實例化此對象 5 { 6 } 7 public static Singleton Instance 8 { 9 get { 10 if (instance == null) //起到延遲加載對象的作用,當用戶用不到此實例的時候 11 { 12 instance = new Singleton(); 13 } 14 return instance; 15 } 16 } 17 }
單線程Singleton模式的幾個要點
????????????????? ? Singleton模式中的實例構造器可以設置為protected以允許子類派生。(同樣不可實例化對象,受保護級別限制)
????????????????? ? Singleton模式一般不要支持ICloneable接口(實例克隆),因為這可能會導致多個對象實例,與Singleton模式的初衷違背。(實現了ICloneable接口,就必須實現Clone()方法,在此方法中我們可以返回新的對象,這樣就與Singleton模式相違背了!)
????????????????? ? Singleton模式一般不要支持序列化,因為這也有可能導致多個對象實例,同樣與Singleton模式的初衷違背。(構造對象的方式:可以通過構造器,也可以通過序列化構造對象,序列化出來的對象和原來的對象地址是不一樣的,是完全的深拷貝方式(創建新的對象))
??????????????????? Singletom模式只考慮到了對象創建的管理,沒有考慮對象銷毀的管理。就支持垃圾回收的平臺和對象的開銷來講,我們一般沒有必要對其銷毀進行特殊的管理。
????????? (缺點)? 不能應對多線程環境:在多線程環境下,使用Singleton模式仍然有可能得到Singleton類的多個實例對象。(在上面的代碼第10行進行if判斷的時候,假設現在有兩個線程(A,B)同時執行到了此行,當A線程進行if判斷,此時判斷為null,就去實例化對象,但是A線程還沒來得及進行對象的實例化的時候,此時B線程就進行了if的判斷,并完成了對此對象的判斷,判斷為null,所以B線程就會去創建另一個實例,所以就創建了兩個實例!)
????4.2、多線程Singleton 模式實現
1 class Singleton 2 { 3 private static volatile Singleton instance = null; //volatile(編譯器在對代碼進行編譯的時候,會對代碼進行一些微調,對代碼的順序進行調整,
volatile關鍵字就保證了編譯器不會對instance進行代碼的微調,
這樣就保證了嚴格意義上的多線程不會出現創建出多個實例的情況) 4 private static object lockHelper = new object(); //輔助器 5 private Singleton() //防止外界隨意new此對象 6 { 7 } 8 public static Singleton Instance 9 { 10 get 11 { 12 if (instance == null) 13 { 14 lock (lockHelper) 15 { 16 if (instance == null)//雙檢查 17 { 18 instance = new Singleton(); 19 } 20 } 21 } 22 return instance; 23 } 24 } 25 }
優缺點:這種實現方式對多線程來說是安全的,同時線程不是每次都加鎖,只有判斷對象實例沒有被創建時它才加鎖(如果最外層的if不加的話,那么其他線程都會進行加鎖操作,會增加額外的開銷,損失性能),加鎖后還得再進行對象是否已被創建的判斷。它解決了線程并發問題,同時避免在每個 Instance 屬性方法的調用中都出現獨占鎖定。它還允許您將實例化延遲到第一次訪問對象時發生。
volatile:
MSDN上的解釋:volatile 關鍵字表示字段可能被多個并發執行線程修改。聲明為 volatile 的字段不受編譯器優化(假定由單個線程訪問)的限制。這樣可以確保該字段在任何時間呈現的都是最新的值
???? 4.3、?使用.NET類型初始化機制實現多線程Singleton 模式(最好的方式)
1 sealed class Singleton 2 { 3 private static readonly Singleton instance = new Singleton(); 4 private Singleton() //防止外界隨意new此對象 5 { 6 } 7 }
其實上面的代碼實現如果展開來的話等同于下面代碼的實現
1 sealed class Singleton 2 { 3 private static readonly Singleton instance; 4 static Singleton() //在調用instance靜態字段時會先去執行此靜態構造器,靜態構造器能保證多線程環境下只有一個線程執行了此靜態構造器,為我們自動加鎖 5 { 6 instance = new Singleton();//在靜態構造器中實例化 7 } 8 private Singleton() //防止外界隨意new此對象 9 { 10 } 11 }
該類標記為 sealed 以阻止發生派生,而派生可能會增加實例。此外,變量標記為 readonly,這意味著只能在靜態初始化期間(此處顯示的示例)或在類構造函數中分配變量。
缺點:
- 我們對實例化機制的控制權較少!在4.1和4.2中能夠在實例化之前使用非默認的構造函數或執行其他任務。由于在此實現方法中由 .NET Framework負責執行初始化,因此您沒有這些選項。
- 無法實現延遲初始化,
- 4.3的實現方法無法進行傳參,4.1和4.2的實現方式都可以進行傳參,主要是因為對象的實例化是在方法內部創建的(屬性實質為方法),所以我們可以把屬性寫成帶參數的方法即可!如下,對4.1方法變為帶參數的!
1 class Singleton 2 { 3 private static Singleton instance; 4 public string Name { get; set; } 5 public int Age { get; set; } 6 public static Singleton GetInstance(string name, int age) 7 { 8 if (instance == null) 9 { 10 instance = new Singleton(name, age); 11 } 12 return instance; 13 } 14 private Singleton(string name, int age) 15 { 16 this.Name = name; 17 this.Age = age; 18 } 19 }
5、延遲初始化
1 public sealed class Singleton 2 { 3 Singleton() 4 { 5 } 6 public static Singleton Instance 7 { 8 get 9 { 10 return Nested.instance; 11 } 12 } 13 class Nested 14 { 15 static Nested() 16 { 17 } 18 internal static readonly Singleton instance = new Singleton(); 19 } 20 }
?這里,初始化工作有Nested類的一個靜態成員來完成,這樣就實現了延遲初始化,并具有很多的優勢,是值得推薦的一種實現方式?
6、Singleton模式擴展
??????????? ? 將一個實例擴展到固定幾個實例,例如對象池的實現。這樣做是允許的而且是有意義的!
??????????? ? 將new 構造器的調用轉移到其他類中,例如多個類協同工作環境中,某個局部環境只需要擁有某個類的一個實例。
??????????? ? 理解和擴展Singleton模式的核心是“如何控制用戶使用new對一個類的實例構造器的任意調用”。?
?7、.NET框架中的Singleton應用
- winform程序,你只需要點擊按鈕,彈出一個窗口,并且保證此窗口只能有一個!再點擊按鈕是無法在彈出此窗體的!
- PC機中可能有幾個串口,但只能有一個COM1口的實例。
- 系統中只能有一個窗口管理器。
- .NET Remoting中服務器激活對象中的Sigleton對象,確保所有的客戶程序的請求都只有一個實例來處理。
?
?8、推薦參考書
??????????? ? 《設計模式:可復用面向對象軟件的基礎》GoF???????????????????????????? --小白看起來會有點困難
??????????? ? 《面向對象分析與設計》Grady Booch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --翻譯有些問題
??????????? ? 《敏捷軟件開發:原則、模式與實踐》Robert C. Martin
????????????? 《重構:改善既有代碼的設計》 Martin Fowler
??????????? ? 《Refactoring to Patterns》Joshua Kerievsky???????????????????????? --沒中文版
?9、參考
??? 《C#面向對象設計模式縱橫談》 ? ?李建忠
???? http://terrylee.cnblogs.com??? TerryLee
?
????????????????????????????????????????????????????????????????????????????????????????????????? 作者:MrZivChu
2013-08-02 15:34:03
?
?
?
?
?
?
?
?
?
?
?
?