Singleton patterns 单件(创建型模式)
1、模式分類
???? 1.1? 從目的來看:
??????????????????? ?????? – 創(chuàng)建型(Creational)模式:負(fù)責(zé)對象創(chuàng)建。
??????????????????? ?????? – 結(jié)構(gòu)型(Structural)模式:處理類與對象間的組合。
?????????????????????????? – 行為型(Behavioral)模式:類與對象交互中的職責(zé)分配。
???? 1.2 從范圍來看:
????????????????????????? – 類模式處理類與子類的靜態(tài)關(guān)系。
??????????????????? ????? – 對象模式處理對象間的動態(tài)關(guān)系。
2、動機(jī)(Motivation)目的??
????????????????????在軟件系統(tǒng)中,經(jīng)常有這樣一些特殊的類,必須保證它們在系統(tǒng)中只存在一個實例,才能確保它們的邏輯正確性、以及良好的效率。
3、意圖(Intent) ????????????
??????????????????? 保證一個類僅有一個實例,并提供一個該實例的全局訪問點。
????????????????????????????????????????????????????????????????????????????????????????? ——《設(shè)計模式》GoF
4、單例模式多種實現(xiàn)方法
??? 4.1 單線程Singleton 模式實現(xiàn)
1 class Singleton 2 { 3 private static Singleton instance; 4 private Singleton() //防止外界隨意new此對象,如果訪問級別設(shè)置成protected,那么子類可以派生,同時也也不可以實例化此對象 5 { 6 } 7 public static Singleton Instance 8 { 9 get { 10 if (instance == null) //起到延遲加載對象的作用,當(dāng)用戶用不到此實例的時候 11 { 12 instance = new Singleton(); 13 } 14 return instance; 15 } 16 } 17 }單線程Singleton模式的幾個要點
????????????????? ? Singleton模式中的實例構(gòu)造器可以設(shè)置為protected以允許子類派生。(同樣不可實例化對象,受保護(hù)級別限制)
????????????????? ? Singleton模式一般不要支持ICloneable接口(實例克隆),因為這可能會導(dǎo)致多個對象實例,與Singleton模式的初衷違背。(實現(xiàn)了ICloneable接口,就必須實現(xiàn)Clone()方法,在此方法中我們可以返回新的對象,這樣就與Singleton模式相違背了!)
????????????????? ? Singleton模式一般不要支持序列化,因為這也有可能導(dǎo)致多個對象實例,同樣與Singleton模式的初衷違背。(構(gòu)造對象的方式:可以通過構(gòu)造器,也可以通過序列化構(gòu)造對象,序列化出來的對象和原來的對象地址是不一樣的,是完全的深拷貝方式(創(chuàng)建新的對象))
??????????????????? Singletom模式只考慮到了對象創(chuàng)建的管理,沒有考慮對象銷毀的管理。就支持垃圾回收的平臺和對象的開銷來講,我們一般沒有必要對其銷毀進(jìn)行特殊的管理。
????????? (缺點)? 不能應(yīng)對多線程環(huán)境:在多線程環(huán)境下,使用Singleton模式仍然有可能得到Singleton類的多個實例對象。(在上面的代碼第10行進(jìn)行if判斷的時候,假設(shè)現(xiàn)在有兩個線程(A,B)同時執(zhí)行到了此行,當(dāng)A線程進(jìn)行if判斷,此時判斷為null,就去實例化對象,但是A線程還沒來得及進(jìn)行對象的實例化的時候,此時B線程就進(jìn)行了if的判斷,并完成了對此對象的判斷,判斷為null,所以B線程就會去創(chuàng)建另一個實例,所以就創(chuàng)建了兩個實例!)
????4.2、多線程Singleton 模式實現(xiàn)
1 class Singleton 2 { 3 private static volatile Singleton instance = null; //volatile(編譯器在對代碼進(jìn)行編譯的時候,會對代碼進(jìn)行一些微調(diào),對代碼的順序進(jìn)行調(diào)整,volatile關(guān)鍵字就保證了編譯器不會對instance進(jìn)行代碼的微調(diào),
這樣就保證了嚴(yán)格意義上的多線程不會出現(xiàn)創(chuàng)建出多個實例的情況) 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 }
優(yōu)缺點:這種實現(xiàn)方式對多線程來說是安全的,同時線程不是每次都加鎖,只有判斷對象實例沒有被創(chuàng)建時它才加鎖(如果最外層的if不加的話,那么其他線程都會進(jìn)行加鎖操作,會增加額外的開銷,損失性能),加鎖后還得再進(jìn)行對象是否已被創(chuàng)建的判斷。它解決了線程并發(fā)問題,同時避免在每個 Instance 屬性方法的調(diào)用中都出現(xiàn)獨占鎖定。它還允許您將實例化延遲到第一次訪問對象時發(fā)生。
volatile:
MSDN上的解釋:volatile 關(guān)鍵字表示字段可能被多個并發(fā)執(zhí)行線程修改。聲明為 volatile 的字段不受編譯器優(yōu)化(假定由單個線程訪問)的限制。這樣可以確保該字段在任何時間呈現(xiàn)的都是最新的值
???? 4.3、?使用.NET類型初始化機(jī)制實現(xiàn)多線程Singleton 模式(最好的方式)
1 sealed class Singleton 2 { 3 private static readonly Singleton instance = new Singleton(); 4 private Singleton() //防止外界隨意new此對象 5 { 6 } 7 }其實上面的代碼實現(xiàn)如果展開來的話等同于下面代碼的實現(xiàn)
1 sealed class Singleton 2 { 3 private static readonly Singleton instance; 4 static Singleton() //在調(diào)用instance靜態(tài)字段時會先去執(zhí)行此靜態(tài)構(gòu)造器,靜態(tài)構(gòu)造器能保證多線程環(huán)境下只有一個線程執(zhí)行了此靜態(tài)構(gòu)造器,為我們自動加鎖 5 { 6 instance = new Singleton();//在靜態(tài)構(gòu)造器中實例化 7 } 8 private Singleton() //防止外界隨意new此對象 9 { 10 } 11 }該類標(biāo)記為 sealed 以阻止發(fā)生派生,而派生可能會增加實例。此外,變量標(biāo)記為 readonly,這意味著只能在靜態(tài)初始化期間(此處顯示的示例)或在類構(gòu)造函數(shù)中分配變量。
缺點:
- 我們對實例化機(jī)制的控制權(quán)較少!在4.1和4.2中能夠在實例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)。由于在此實現(xiàn)方法中由 .NET Framework負(fù)責(zé)執(zhí)行初始化,因此您沒有這些選項。
- 無法實現(xiàn)延遲初始化,
- 4.3的實現(xiàn)方法無法進(jìn)行傳參,4.1和4.2的實現(xiàn)方式都可以進(jìn)行傳參,主要是因為對象的實例化是在方法內(nèi)部創(chuàng)建的(屬性實質(zhì)為方法),所以我們可以把屬性寫成帶參數(shù)的方法即可!如下,對4.1方法變?yōu)閹?shù)的!
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類的一個靜態(tài)成員來完成,這樣就實現(xiàn)了延遲初始化,并具有很多的優(yōu)勢,是值得推薦的一種實現(xiàn)方式?
6、Singleton模式擴(kuò)展
??????????? ? 將一個實例擴(kuò)展到固定幾個實例,例如對象池的實現(xiàn)。這樣做是允許的而且是有意義的!
??????????? ? 將new 構(gòu)造器的調(diào)用轉(zhuǎn)移到其他類中,例如多個類協(xié)同工作環(huán)境中,某個局部環(huán)境只需要擁有某個類的一個實例。
??????????? ? 理解和擴(kuò)展Singleton模式的核心是“如何控制用戶使用new對一個類的實例構(gòu)造器的任意調(diào)用”。?
?7、.NET框架中的Singleton應(yīng)用
- winform程序,你只需要點擊按鈕,彈出一個窗口,并且保證此窗口只能有一個!再點擊按鈕是無法在彈出此窗體的!
- PC機(jī)中可能有幾個串口,但只能有一個COM1口的實例。
- 系統(tǒng)中只能有一個窗口管理器。
- .NET Remoting中服務(wù)器激活對象中的Sigleton對象,確保所有的客戶程序的請求都只有一個實例來處理。
?
?8、推薦參考書
??????????? ? 《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》GoF???????????????????????????? --小白看起來會有點困難
??????????? ? 《面向?qū)ο蠓治雠c設(shè)計》Grady Booch ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? --翻譯有些問題
??????????? ? 《敏捷軟件開發(fā):原則、模式與實踐》Robert C. Martin
????????????? 《重構(gòu):改善既有代碼的設(shè)計》 Martin Fowler
??????????? ? 《Refactoring to Patterns》Joshua Kerievsky???????????????????????? --沒中文版
?9、參考
??? 《C#面向?qū)ο笤O(shè)計模式縱橫談》 ? ?李建忠
???? http://terrylee.cnblogs.com??? TerryLee
?
????????????????????????????????????????????????????????????????????????????????????????????????? 作者:MrZivChu
2013-08-02 15:34:03
?
?
?
?
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/MrZivChu/p/Singleton_patterns.html
總結(jié)
以上是生活随笔為你收集整理的Singleton patterns 单件(创建型模式)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络下载器 迅雷大众版 v7.9.42.
- 下一篇: 吉林大学超星学习通高级语言程序设计(C语