设计模式学习笔记十:单例模式(Singleton Pattern)
生活随笔
收集整理的這篇文章主要介紹了
设计模式学习笔记十:单例模式(Singleton Pattern)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
????1.概述
????單例模式(Singleton Pattern)又稱單件模式,單例模式保證一個類僅有一個實例,并提供一個訪問的他的全局訪問點。通常我們可以讓一個全局變量使得一個對象被訪問,但它不能防止你實例化對個對象,一個最好的辦法就是,讓類自身負責保存他的唯一實例,這個類可以保證沒有其他實例可以被創(chuàng)建并且他可以提供一個訪問該實例的方法。
????使用場合:當類只能有一個實例存在,并且可以在全局訪問時,這個唯一的實例應(yīng)該可以通過子類實現(xiàn)擴展,并且用戶無須更改代碼即可使用。前面學習過得工廠類經(jīng)常被實例化為全局唯一的單件,可能的單件還有系統(tǒng)的管理日志的對象、關(guān)鍵字生成對象和外部設(shè)備接口對象等。
????結(jié)構(gòu):
Singleton
????public?class?Singleton
????{
????????private?static?Singleton?instance;
????????private?static?readonly?object?syncRoot?=?new?object();
????????private?Singleton()
????????{
????????}
????????public?static?Singleton?GetInstance()
????????{
????????????if?(instance?==?null)
????????????{
????????????????instance?=?new?Singleton();
????????????}
????????????return?instance;
????????}
????}
????單例模式提供了全局唯一的訪問入口,易于控制可能發(fā)生的沖突。
????單例模式因為Singleton類封裝它的唯一實例,這樣他可以嚴格的控制客戶怎樣訪問它以及何時訪問他。
????單例模式是對靜態(tài)方法的一種改進,首先避免了全局變量對系統(tǒng)的污染,其次他可以有子類,可以定義虛方法,具有多態(tài)性。而類中的靜態(tài)方法是不能被定義為虛方法,因此不具有多態(tài)性。
????2.實例
????1.單件計數(shù)器
????最簡單的單例模式應(yīng)用就是計數(shù)器,在基于Web的應(yīng)用中,我們希望有一個全局計數(shù)器來統(tǒng)計單件的次數(shù),為此我們要定義一個單件計數(shù)器:
Counter
????/**////?<summary>
????///?計數(shù)器
????///?</summary>
????public?class?Counter
????{
????????private?int?intCounter?=?0;
????????private?static?Counter?MyCounter;
????????public?int?Count()
????????{
????????????intCounter?=?intCounter?+?1;
????????????return?intCounter;
????????}
????????public?static?Counter?GetInstance()
????????{
????????????if?(MyCounter?==?null)
????????????{
????????????????MyCounter?=?new?Counter();
????????????}
????????????return?MyCounter;
????????}
????}
????調(diào)用代碼:
????????????for?(int?i?=?0;?i?<?10;?i++)
????????????{
????????????????Console.WriteLine(Counter.GetInstance().Count());
????????????} ????2.多線程時的單例以及雙重鎖定
????在多線程程序中,多個線程同時訪問Singleton類時,調(diào)用GetInstance()方法,會有可能造成創(chuàng)建多個實例,我們可以給進程加一把鎖來處理。鎖(Lock)是確保當一個線程位于代碼的臨界區(qū)時,另一個線程不能進入該臨界區(qū),如果其他線程試圖進入鎖定的代碼,則他將一直等待(即被阻止),直到該對象被釋放【MSDN】。?
????下面來看加鎖的單例模式:
Singleton
????public?class?Singleton
????{
????????private?static?Singleton?instance;
????????private?static?readonly?object?syncRoot?=?new?object();
????????private?Singleton()
????????{
????????}
????????public?static?Singleton?GetInstance()
????????{
????????????lock?(syncRoot)
????????????{
????????????????if?(instance?==?null)
????????????????{
????????????????????instance?=?new?Singleton();
????????????????}
????????????}
????????????return?instance;
????????}
????}
????上面的代碼中的對象實例由最先進入的那個線程創(chuàng)建,以后的線程在進入時不會再去創(chuàng)建對象實例了。由于有了Lock,就保證了多線程環(huán)境下的同時訪問也不會造成多個實例的生成。
????我們不經(jīng)要問,為什么不直接lock呢,而是創(chuàng)建一個SyncRoot來Lock呢?因為在我們加鎖的時候,instance實例有沒有被創(chuàng)建過實例我們都還不知道呢,我們不可能對其加鎖的。上面我們=每次調(diào)用GetInstance()方法時,都需要Lock,這樣會影響性能的。所以我們再做一定的改良優(yōu)化,看下面的代碼:
Singleton
????public?class?Singleton
????{
????????private?static?Singleton?instance;
????????private?static?readonly?object?syncRoot?=?new?object();
????????private?Singleton()
????????{
????????}
????????public?static?Singleton?GetInstance()
????????{
????????????if?(instance?==?null)
????????????{
????????????????lock?(syncRoot)
????????????????{
????????????????????if?(instance?==?null)
????????????????????{
????????????????????????instance?=?new?Singleton();
????????????????????}
????????????????}
????????????}
????????????return?instance;
????????}
????} ????現(xiàn)在,我們就不用讓線程每次都加鎖了,而只是在實例未被創(chuàng)建的時候才加鎖,同時也保證了多線程的安全,這種做法就是Double-Check Locking (雙重鎖定)。到這兒我們不經(jīng)會問,我在外面已經(jīng)判斷了instance實例是否存在,為什么在lock里面還要判斷呢?我們具體的來分析,對于instance存在的情況,就直接返回,這沒有問題,當instance位null并且同時有兩個線程調(diào)用GetInstance()方法時,他們同時會通過第一重判斷,然后由于Lock機制,則這兩個線程只能進入一個,另一個則只能排隊等候,必須其中一個進入并出來后,他才能進入。而此時如果沒有了第二重的判斷,則第一個線程創(chuàng)建了實例,而第二個線程還是可以繼續(xù)創(chuàng)建新的實例,這樣就沒有達到單例模式的目的。
????3.靜態(tài)初始化
????在.Net中公共語言運行庫中也提供了一種“靜態(tài)初始化”方法,這種方法不需要顯示的編寫線程安全代碼,即可解決多線程環(huán)境下單例模式不安全的問題.看下面簡單的代碼:
Singleton
????public?sealed?class?Singleton
????{
????????private?static?readonly?Singleton?instance?=?new?Singleton();
????????private?Singleton()?{?}
????????public?static?Singleton?GetInstance()
????????{
????????????return?instance;
????????}
????} ????這種靜態(tài)初始化的方法是自己被加載時就自己實例化,被形象的稱之為惡漢式單例類。而原先的單例模式處理方式要在第一次被引用的時候才會被實例化,就被稱為懶漢式單例類。
????3.總結(jié)
????全局變量與單例模式:單例模式維護了自身的實例化,在使用上是安全的,一個全局對象無法自行維護,也就無法規(guī)避重復創(chuàng)建對象實例,系統(tǒng)資源會被大量占用,更糟糕的是會出現(xiàn)邏輯問題。
????單件與實用類中的靜態(tài)方法:
????實用類是提供系統(tǒng)公用的靜態(tài)方法,并且也經(jīng)常采用私有的構(gòu)造方法,與單例不同,他沒有實例,其中的方法全是靜態(tài)方法。實用類和單例模式的區(qū)別如下:
????1).實用類不保存狀態(tài),僅提供功能。2)實用類不具有多態(tài)性,而單例類可以有子類。3)單例是對象,而實用類只是方法的集合。
轉(zhuǎn)載于:https://www.cnblogs.com/peida/archive/2008/06/27/1230756.html
總結(jié)
以上是生活随笔為你收集整理的设计模式学习笔记十:单例模式(Singleton Pattern)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vb.net中的-String类
- 下一篇: JSP上传组件