日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设计模式之单件模式(Singleton Pattern)

發布時間:2023/12/2 asp.net 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式之单件模式(Singleton Pattern) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.單件模式是什么?

單件模式也被稱為單例模式,它的作用說白了就是為了確?!霸擃惖膶嵗挥幸粋€”

單件模式經常被用來管理資源敏感的對象,比如:數據庫連接對象、注冊表對象、線程池對象等等,這種對象如果同時存在多個的話就會造成各種不一致的麻煩(你總不希望發生數據庫重復連接的異常吧)

二.如何保證類的實例只有一個?

(這個問題看似簡單,但如果沒有接觸過單件模式的話,要自己想出來解決方案還是需要一些天賦的。。不信的話,可以試著想想。。)

1.類的實例可能只有一個嗎?貌似只要知道類名就可以隨便new了吧?

當然可以,知道類名的話,確實可以調用其構造方法來new實例,但是,注意一點:這個類必須要有公開的構造方法才能從外部new實例,不是嗎?

2.那就是說要保證類的實例只有一個的話,這個類不能有公開的構造方法,對吧?

沒錯,就是這樣,我們需要定義一個私有的構造方法

3.一個沒有公開構造方法的類能夠產生實例嗎?如果構造方法是private,那么只有該類的實例才能調用這個構造方法,同樣的要調用這個構造方法才能產生該類的實例。。這不是“雞生蛋,蛋生雞。?!钡膯栴}嗎?

用私有的構造方法當然可以生產實例,上面忽略了一點:并不是“只有該類的實例才能調用這個構造方法”

因為在該類內部就可以隨便調用這個私有的構造方法,并不需要創建任何實例

-------

有了上面的討論結果,我們就可以實現經典的單件模式了:

package SingletonPattern;/*** @author ayqy* 最經典的單件模式*/ public class Singleton {private static Singleton instance;//定義靜態實例變量/*** 定義私有構造方法,防止從外部new實例*/private Singleton(){//初始化操作}/*** 提供全局訪問點* @return 該類的實例*/public static Singleton getInstance(){if(instance == null)instance = new Singleton();return instance;}/** 其它有用的屬性和行為* 畢竟應用了單件模式的類仍然具有原本的功能* */ }

注意:一定要清楚最后一點,應用了單件模式的類并不應該喪失其原本的功能,千萬不能為了使用而使用

三.繼續思考我們的單件模式

我們的單件模式已經萬無一失了嗎?

不,它還存在很多問題,比如:

1.多線程環境下

2.多個class loader環境下

我們無法保證產生的實例只有一個,對吧?

但是作為一種成熟的設計模式,單件模式必須要能從容應對這些環境,所以,接下來我們將討論如何應對這些環境

四.多線程環境下的單件模式

如何在多線程環境下保證實例的唯一性?

很容易想到用synchronized關鍵字來保證線程安全,就像這樣:

/*** 提供全局訪問點* @return 該類的實例*/ public static synchronized Singleton getInstance(){if(instance == null)instance = new Singleton();return instance; }

我們把getInstance方法定義為同步方法就保證了不會有多個線程同時進入該方法,就不會產生不同的實例了

-------

但是上面的方法存在致命的問題:用synchronized關鍵字同步方法會極大的降低效率(同步一個方法甚至可能造成百倍的效率下降。。),這會拖垮我們的程序

有什么好的改進方法呢?

首先,上面的同步塊是整個getIntance方法,每次調用該方法都會強制進入同步機制,但仔細一想,我們只在第一此調用該方法時需要進行同步(第一次new對象),之后的調用直接返回new好的對象就好了

那么,我們的改進方案就是:用雙重加鎖實現只在第一次new對象時進行同步

package SingletonPattern;/*** @author ayqy* 多線程下的單件模式2——利用雙重加鎖保證只在實例化變量的時候進行同步*/ public class DoubleLockSingleton {private static volatile DoubleLockSingleton instance;//定義靜態實例變量/*** 定義私有構造方法,防止從外部new實例*/private DoubleLockSingleton(){//初始化操作}/*** 提供全局訪問點* @return 該類的實例*/public static DoubleLockSingleton getInstance(){if(instance == null)synchronized(DoubleLockSingleton.class){//進入同步塊if(instance == null)//再次判空instance = new DoubleLockSingleton();}return instance;}/** 其它有用的屬性和行為* 畢竟應用了單件模式的類仍然具有原本的功能* */ }

注意:雙重加鎖體現在volatile關鍵字(告訴編譯器,這個變量不能被保留副本,一旦發生變動就會強制寫回,避免了不一致)和synchronized修飾的同步塊

但要明白這樣做的代價,volatile關鍵字也會告訴編譯器,不要對該對象進行編譯優化

只看第一次new對象的過程的話,雙重加鎖的效率甚至要比同步方法更低,但在雙重加鎖方式在以后的調用中不再需要進行同步,所以長遠看來雙重加鎖的效率要高于同步方法

-------

有沒有一種方法不需要使用龜速的同步機制就能保證線程安全呢?如果有的話,絕對能夠大大提高效率,對吧?

當然有,這種方法叫做“急切初始化”(順便提一下,開篇提到的“經典單件模式”其實用了“延遲初始化”的方法。。很簡單,不必解釋),一起看看吧:

package SingletonPattern;/*** @author ayqy* 多線程環境下的單件模式——用“急切初始化”來保證線程安全*/ public class EagerlyInitSingleton {private static EagerlyInitSingleton instance = new EagerlyInitSingleton();//定義靜態實例變量,并在類加載的時候就進行初始化操作/*** 定義私有構造方法,防止從外部new實例*/private EagerlyInitSingleton(){//初始化操作}/*** 提供全局訪問點* @return 該類的實例*/public static synchronized EagerlyInitSingleton getInstance(){return instance;}/** 其它有用的屬性和行為* 畢竟應用了單件模式的類仍然具有原本的功能* */ }

額,這也能叫方法嗎?這么做貌似不和標準吧?

沒關系,這種方法自然有它的優點,比如:

1.效率很高,且線程安全

2.簡單易用,什么都不用考慮,甚至不用判斷

但其致命的缺點是:資源浪費問題,如果這個對象是一個巨大的極其耗費資源的對象,而我們在一開始就創建了它,卻遲遲沒有用到,這將是非常傷的。。

-------

上面提到了三種保證線程同步的方式,如何選擇必須要結合具體情況來定,應綜合考慮效率,資源利用等各個因素

五.多個class loader環境下的單件模式

如果存在多個類加載器,多個類加載器可能同時加載我們的單件類,從而產生多個實例

對于這種情況,我們可以顯式指定使用哪一個class loader來加載單件類,這樣就有效避免了上述問題

六.總結

應用單件模式可以保證對象的唯一性,但要注意單件模式的適用范圍

不應該濫用單件模式,因為畢竟需要管理的資源敏感對象不會很多

轉載于:https://www.cnblogs.com/ayqy/p/3962910.html

總結

以上是生活随笔為你收集整理的设计模式之单件模式(Singleton Pattern)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。