單件模式61375_第1頁
單件模式61375_第2頁
單件模式61375_第3頁
單件模式61375_第4頁
單件模式61375_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、單件模式(Singleton Pattern)設(shè)計模式之1設(shè)計模式設(shè)計模式是規(guī)則嗎?地上本沒有路,走得人多了也就成了路。設(shè)計模式如同此理,它是經(jīng)驗的傳承,并非體系;是被前人發(fā)現(xiàn),經(jīng)過總結(jié)形成了一套某一類問題的一般性解決方案,而不是被設(shè)計出來的定性規(guī)則;它不像算法那樣可以照搬照用。設(shè)計模式是架構(gòu)嗎?架構(gòu)和模式應(yīng)該是一個屬于相互涵蓋的過程,但是總體來說架構(gòu)更加關(guān)注的是所謂的High-Level Design,而模式關(guān)注的重點在于通過經(jīng)驗提取的“準(zhǔn)則或指導(dǎo)方案”在設(shè)計中的應(yīng)用,因此在不同層面考慮問題的時候就形成了不同問題域上的模式。模式的目標(biāo)是,把共通問題中的不變部分和變化部分分離出來。不變的部分,

2、就構(gòu)成了模式,因此,模式是一個經(jīng)驗提取的“準(zhǔn)則”,并且在一次一次的實踐中得到驗證,在不同的層次有不同的模式,小到語言實現(xiàn),大到架構(gòu)。在不同的層面上,模式提供不同層面的指導(dǎo)。設(shè)計模式,軟件的永恒之道?2單件模式(Singleton Pattern) Singleton模式要求一個類有且僅有一個實例,并且提供了一個全局的訪問點。這就提出了一個問題:如何繞過常規(guī)的構(gòu)造器,提供一種機(jī)制來保證一個類只有一個實例?客戶程序在調(diào)用某一個類時,它是不會考慮這個類是否只能有一個實例等問題的,所以,這應(yīng)該是類設(shè)計者的責(zé)任,而不是類使用者的責(zé)任。 從另一個角度來說,Singleton模式其實也是一種職責(zé)型模式。因為

3、我們創(chuàng)建了一個對象,這個對象扮演了獨一無二的角色,在這個單獨的對象實例中,它集中了它所屬類的所有權(quán)力,同時它也肩負(fù)了行使這種權(quán)力的職責(zé)! 3意圖 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 模型圖 4生活中的例子 美國總統(tǒng)的職位是Singleton,美國憲法規(guī)定了總統(tǒng)的選舉,任期以及繼任的順序。這樣,在任何時刻只能由一個現(xiàn)任的總統(tǒng)。無論現(xiàn)任總統(tǒng)的身份為何,其頭銜美利堅合眾國總統(tǒng)是訪問這個職位的人的一個全局的訪問點。 5五種實現(xiàn) 1簡單實現(xiàn) 1 publicsealedclassSingleton2 3 staticSingletoninstance=null;4 5 Singlet

4、on()6 7 8 9 publicstaticSingletonInstance10 11 get12 13 if(instance=null)14 15 instance=newSingleton();16 17 returninstance;18 19 20 6這種方式的實現(xiàn)對于線程來說并不是安全的,因為在多線程的環(huán)境下有可能得到Singleton類的多個實例。如果同時有兩個線程去判斷(instance = null),并且得到的結(jié)果為真,這時兩個線程都會創(chuàng)建類Singleton的實例,這樣就違背了Singleton模式的原則。實際上在上述代碼中,有可能在計算出表達(dá)式的值之前,對象實例已

5、經(jīng)被創(chuàng)建,但是內(nèi)存模型并不能保證對象實例在第二個線程創(chuàng)建之前被發(fā)現(xiàn)。 該實現(xiàn)方式主要有兩個優(yōu)點: 由于實例是在 Instance 屬性方法內(nèi)部創(chuàng)建的,因此類可以使用附加功能(例如,對子類進(jìn)行實例化),即使它可能引入不想要的依賴性。 直到對象要求產(chǎn)生一個實例才執(zhí)行實例化;這種方法稱為“惰性實例化”。惰性實例化避免了在應(yīng)用程序啟動時實例化不必要的 singleton。 72安全的線程 1 publicsealedclassSingleton2 3 staticSingletoninstance=null;4 staticreadonlyobjectpadlock=newobject();5 6 S

6、ingleton()7 8 9 10 publicstaticSingletonInstance11 12 get13 14 lock(padlock)15 16 if(instance=null)17 18 instance=newSingleton();19 20 returninstance;21 22 23 24 25 26 8這種方式的實現(xiàn)對于線程來說是安全的。我們首先創(chuàng)建了一個進(jìn)程輔助對象,線程在進(jìn)入時先對輔助對象加鎖然后再檢測對象是否被創(chuàng)建,這樣可以確保只有一個實例被創(chuàng)建,因為在同一個時刻加了鎖的那部分程序只有一個線程可以進(jìn)入。這種情況下,對象實例由最先進(jìn)入的那個線程創(chuàng)建,后來的

7、線程在進(jìn)入時(instence = null)為假,不會再去創(chuàng)建對象實例了。但是這種實現(xiàn)方式增加了額外的開銷,損失了性能。 9雙重鎖定 publicsealedclassSingleton2 3 staticSingletoninstance=null;4 staticreadonlyobjectpadlock=newobject();5 6 Singleton()7 8 9 10 publicstaticSingletonInstance11 12 get13 14 if(instance=null)15 16 lock(padlock)17 18 if(instance=null)19 2

8、0 instance=newSingleton();21 22 23 24 returninstance;25 26 27 28 10這種實現(xiàn)方式對多線程來說是安全的,同時線程不是每次都加鎖,只有判斷對象實例沒有被創(chuàng)建時它才加鎖,有了我們上面第一部分的里面的分析,我們知道,加鎖后還得再進(jìn)行對象是否已被創(chuàng)建的判斷。它解決了線程并發(fā)問題,同時避免在每個 Instance 屬性方法的調(diào)用中都出現(xiàn)獨占鎖定。它還允許您將實例化延遲到第一次訪問對象時發(fā)生。實際上,應(yīng)用程序很少需要這種類型的實現(xiàn)。大多數(shù)情況下我們會用靜態(tài)初始化。這種方式仍然有很多缺點:無法實現(xiàn)延遲初始化。 114靜態(tài)初始化 1 public

9、sealedclassSingleton2 3 staticreadonlySingletoninstance=newSingleton();4 5 staticSingleton()6 7 8 9 Singleton()10 11 12 13 publicstaticSingletonInstance14 15 get16 17 returninstance;18 19 20 21 12看到上面這段富有戲劇性的代碼,我們可能會產(chǎn)生懷疑,這還是Singleton模式嗎?在此實現(xiàn)中,將在第一次引用類的任何成員時創(chuàng)建實例。公共語言運行庫負(fù)責(zé)處理變量初始化。該類標(biāo)記為 sealed 以阻止發(fā)生派生,

10、而派生可能會增加實例。此外,變量標(biāo)記為 readonly,這意味著只能在靜態(tài)初始化期間(此處顯示的示例)或在類構(gòu)造函數(shù)中分配變量。 該實現(xiàn)與前面的示例類似,不同之處在于它依賴公共語言運行庫來初始化變量。它仍然可以用來解決 Singleton 模式試圖解決的兩個基本問題:全局訪問和實例化控制。公共靜態(tài)屬性為訪問實例提供了一個全局訪問點。此外,由于構(gòu)造函數(shù)是私有的,因此不能在類本身以外實例化 Singleton 類;因此,變量引用的是可以在系統(tǒng)中存在的唯一的實例。 由于 Singleton 實例被私有靜態(tài)成員變量引用,因此在類首次被對 Instance 屬性的調(diào)用所引用之前,不會發(fā)生實例化。 13

11、這種方法唯一的潛在缺點是,您對實例化機(jī)制的控制權(quán)較少。在 Design Patterns 形式中,您能夠在實例化之前使用非默認(rèn)的構(gòu)造函數(shù)或執(zhí)行其他任務(wù)。由于在此解決方案中由 .NET Framework 負(fù)責(zé)執(zhí)行初始化,因此您沒有這些選項。在大多數(shù)情況下,靜態(tài)初始化是在 .NET 中實現(xiàn) Singleton 的首選方法。 145延遲初始化 1 publicsealedclassSingleton2 3 Singleton()4 5 6 7 publicstaticSingletonInstance8 9 get10 11 returnNested.instance;12 13 14 15 cl

12、assNested16 17 staticNested()18 19 20 21 internalstaticreadonlySingletoninstance=newSingleton();22 23 15這里,初始化工作有Nested類的一個靜態(tài)成員來完成,這樣就實現(xiàn)了延遲初始化,并具有很多的優(yōu)勢,是值得推薦的一種實現(xiàn)方式 16實現(xiàn)要點 l Singleton模式是限制而不是改進(jìn)類的創(chuàng)建。 l Singleton類中的實例構(gòu)造器可以設(shè)置為Protected以允許子類派生。 l Singleton模式一般不要支持Icloneable接口,因為這可能導(dǎo)致多個對象實例,與Singleton模式的

13、初衷違背。 l Singleton模式一般不要支持序列化,這也有可能導(dǎo)致多個對象實例,這也與Singleton模式的初衷違背。 l Singleton只考慮了對象創(chuàng)建的管理,沒有考慮到銷毀的管理,就支持垃圾回收的平臺和對象的開銷來講,我們一般沒必要對其銷毀進(jìn)行特殊的管理。 l 理解和擴(kuò)展Singleton模式的核心是“如何控制用戶使用new對一個類的構(gòu)造器的任意調(diào)用”。 l 可以很簡單的修改一個Singleton,使它有少數(shù)幾個實例,這樣做是允許的而且是有意義的17優(yōu)點 實例控制:Singleton 會阻止其他對象實例化其自己的 Singleton 對象的副本,從而確保所有對象都訪問唯一實例 靈活性:因為類控制了實例化過程,所以類可以更加靈活修改實例化過程 18缺點 開銷:雖然數(shù)量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷??梢酝ㄟ^使用靜態(tài)初始化解決此問題,上面的五種實現(xiàn)方式中已經(jīng)說過了。 可能的開發(fā)混淆:使用 singleton 對象(尤其在類庫中定義的對象)時,開發(fā)人員必須記住自己不能使用 new 關(guān)鍵

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論