專業(yè)做傳奇網站解析搜云seo
總目錄
前言
本文是個人基于C#學習設計模式總結的學習筆記,希望對你有用!
1 基本介紹
定義:確保一個類只有一個實例,并提供一個全局訪問點。
本質就是保證在整個應用程序的生命周期中,任何一個時刻,單例類的實例都只存在一個。
2 適用場景
單例模式通常適用于在整個應用程序中只需要一個實例化對象的場景,以確保資源的高效利用和應用程序的穩(wěn)定性。
- 日志系統(tǒng):在應用程序中,通常只需要一個日志系統(tǒng),以避免在多個地方創(chuàng)建多個日志對象。這一般是由于共享的日志文件一直處于打開狀態(tài),所以只能有一個實例去操作,否則內容不好追加也有可能造成資源占用加劇資源消耗。
- 數據庫連接池:在應用程序中,數據庫連接池是一個非常重要的資源,單例模式可以確保在應用程序中只有一個數據庫連接池實例,避免資源浪費。主要是節(jié)省打開或者關閉數據庫連接所引起的效率損耗,因為何用單例模式來維護,就可以大大降低這種損耗。
- 配置文件管理器:在應用程序中,通常只需要一個配置文件管理器來管理應用程序的配置文件,單例模式可以確保在整個應用程序中只有一個配置文件管理器實例。這個是由于配置文件是共享的資源。
- 緩存系統(tǒng):在應用程序中,緩存系統(tǒng)是一個重要的組件,單例模式可以確保在整個應用程序中只有一個緩存實例,以提高應用程序的性能。
- 網站在線人數統(tǒng)計:其實就是全局計數器,也就是說所有用戶在相同的時刻獲取到的在線人數數量都是一致的。
- GUI組件:在圖形用戶界面(GUI)開發(fā)中,單例模式可以確保在整個應用程序中只有一個GUI組件實例,以確保用戶界面的一致性和穩(wěn)定性。
3 實現方式
- 懶漢式:類加載不會導致該單實例對象被創(chuàng)建,而是首次使用該對象時才會創(chuàng)建。
- 餓漢式:類加載就會導致該單實例對象被創(chuàng)建。
- 懶漢式,公有靜態(tài)方法,非線程安全
/// <summary>/// 單例模式的實現/// </summary>public class Singleton{//定義一個靜態(tài)變量用于保存實例private static Singleton instance;private Singleton(){//將構造函數私有化,使外界不能創(chuàng)建該類實例}//定義公有靜態(tài)方法,提供一個全局訪問點(也可以定義公有屬性作為全局訪問點)public static Singleton GetInstance(){if (instance == null){instance = new Singleton();}return instance;}}
在GetInstance方法中,我們檢查instance是否為null,如果是,則創(chuàng)建一個新的Singleton實例并將其賦值給instance。最后,我們返回instance實例。這樣,無論何時調用Instance屬性,它都將返回同一個Singleton實例。通過這種方式,我們實現了單例模式,確保了整個應用程序中只有一個Singleton實例存在,并提供了一個全局訪問點來訪問該實例。
- 懶漢式,公有屬性,非線程安全
/// <summary>/// 單例模式的實現/// </summary>public class Singleton{//定義一個靜態(tài)變量用于保存實例private static Singleton _instance;//定義公有靜態(tài)屬性,提供一個全局訪問點public static Singleton Instance{get {if (_instance == null){_instance = new Singleton();}return _instance;}set { _instance = value; }}private Singleton(){//將構造函數私有化,使外界不能創(chuàng)建該類實例}}
此種方法同上面的方法是一樣的作用,只不過調用的時候,一個是使用方法,一個是使用屬性而已。
- 懶漢式,公有屬性,線程安全
以上的代碼實現了在單線程下是OK的,然而在多線程的情況下會得到多個Singleton 實例,因為在兩個線程同時運行GetInstance方法時,此時兩個線程判斷(_instance ==null)
這個條件時都返回真,此時兩個線程就都會創(chuàng)建Singleton的實例,這樣就違背了我們單例模式初衷了,既然上面的實現會運行多個線程執(zhí)行,那我們對于多線程的解決方案自然就是使GetInstance方法在同一時間只運行一個線程運行就好了
/// <summary>/// 單例模式的實現/// </summary>public class Singleton{//定義一個靜態(tài)變量用于保存實例private static Singleton _instance;//定義一個線程鎖private static readonly object _instanceLock = new object();//定義公有靜態(tài)屬性,提供一個全局訪問點public static Singleton Instance{get {lock (_instanceLock){if (_instance == null){_instance = new Singleton();}}return _instance;}set { _instance = value; }}private Singleton(){//將構造函數私有化,使外界不能創(chuàng)建該類實例}}
- 懶漢式,公有屬性,雙重鎖定,線程安全
上面這種解決方案確實可以解決多線程的問題,但是上面代碼對于每個線程都會對線程輔助對象locker加鎖之后再判斷實例是否存在,對于這個操作完全沒有必要的,因為當第一個線程創(chuàng)建了該類的實例之后,后面的線程此時只需要直接判斷(_instance==null)
為假,此時完全沒必要對線程輔助對象加鎖之后再去判斷,所以上面的實現方式增加了額外的開銷,損失了性能,為了改進上面實現方式的缺陷,我們只需要在lock語句前面加一句(_instance==null)
的判斷就可以避免鎖所增加的額外開銷,這種實現方式我們就叫它 “雙重鎖定”
/// <summary>/// 單例模式的實現/// </summary>public class Singleton{//定義一個靜態(tài)變量用于保存實例private static Singleton _instance;//定義一個線程鎖private static readonly object _instanceLock = new object();//定義公有靜態(tài)屬性,提供一個全局訪問點public static Singleton Instance{get {if (_instance==null){lock (_instanceLock){if (_instance == null){_instance = new Singleton();}}}return _instance;}set { _instance = value; }}private Singleton(){//將構造函數私有化,使外界不能創(chuàng)建該類實例}}
- 餓漢式
/// <summary>/// 單例模式的實現/// </summary>public class Singleton{//定義一個私有靜態(tài)的只讀的全局變量private static readonly Singleton instance = new Singleton();private Singleton(){//將構造函數私有化,使外界不能創(chuàng)建該類實例}//設置為靜態(tài)方法則可在外邊無需創(chuàng)建該類的實例就可調用該方法public static Singleton GetInstance(){return instance;}}
在c#中使用靜態(tài)初始化時無需顯示地編寫線程安全代碼,C# 與 CLR 會自動解決前面提到的懶漢式單例類時出現的多線程同步問題。
當整個類被加載的時候,就會自行初始化 instance 這個靜態(tài)只讀變量。
而非在第一次調用 GetInstance()時再來實例化單例類的唯一實例,所以這就是一種餓漢式的單例類
總結
以上就是今天要講的內容,本文介紹了單例模式的使用,而希望以上內容可以幫助到大家,如文中有不對之處,還請批評指正。
參考資料
C#設計模式(1)——單例模式
C#中單例模式詳解