理解
博友的經典說法:很多人排隊去廁所蹲坑一樣,每一次只能讓一個人去蹲坑,這是一種通俗的理解。
理論上的理解則為,我們需要寫一個類,這個類的作用就是控制,從而保證在整個應用程序的生命周期中,在任何時刻,被調用的類只有一個實例。
設計者需要為使用者提供一個該模式的一個全局訪問點。
代碼理解
入門實例:
public class Singleton { PRivate static Singleton instance; private Singleton() { } public static Singleton GetInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
對代碼的理解:
1、保證在整個應用程序的生命周期中,在任何時刻,被調用的類只有一個實例。如何做到?
第一點就是把類的構造函數私有化,這樣,調用者就不能通過New,來生成實例。
2、private static Singleton instance,該變量的作用,就是返回給調用者的類實例對象。
因為該實例在生命周期中,是唯一的,所以定義一個私有的、靜態的、全局變量instance來保存該類的唯一實例。
3、上述的變量實例是一個私有的,而且我們把類的構造函數私有化了,那么我們就必須寫一個方法來返回類的實例對象。
提供一個全局函數訪問,獲得instance實例,并且在該函數編寫控制實例數目的邏輯,即通過if語句判斷instance是否已被實例化,
如果沒有則可以同new()創建一個實例;否則,直接向客戶返回一個實例。
注意:這種方式的實現對于線程來說并不是安全的,因為在多線程的環境下有可能得到Singleton類的多個實例。如果同時有兩個線程去判斷(instance == null),并且得到的結果為真,這時兩個線程都會創建類Singleton的實例,這樣就違背了Singleton模式的原則。實際上在上述代碼中,有可能在計算出表達式的值之前,對象實例已經被創建,但是內存模型并不能保證對象實例在第二個線程創建之前被發現。(這段話出之:http://m.survivalescaperooms.com/Terrylee/archive/2005/12/09/293509.html)
多線程實例:
public class Singleton{ private static Singleton instance; private static object _lock = new object(); private Singleton() { } public static Singleton GetInstance() { if (instance == null) { lock (_lock) { if (instance == null) { instance = new Singleton(); } } } return instance; }}
對代碼的理解:
1、這段代碼與《入門實例》的區別在與,
# 多了一個變量private static object _lock = new object()
# 在公開方法中對該變量加了鎖
# 在加鎖后,對實例做了判空處理
2、_lock變量申明為私有的、靜態的、全局變量的目的就是保證生命周期中的唯一,這樣對它加鎖后,線程模式下,就會出現加鎖等待。
3、內層的if語句塊中,對實例做了一個空判斷,解決了線程并發問題,同時避免在每個 Instance 屬性方法的調用中都出現獨占鎖定。
它還允許您將實例化延遲到第一次訪問對象時發生。這種方式仍然有很多缺點:無法實現延遲初始化。
注意:這種模式是我們常用的
運行時實例:
public sealed class Singleton{ static readonly Singleton instance = new Singleton(); static Singleton() { } private Singleton() { } public static Singleton Instance { get { return instance; } }}
對代碼的理解:
1、類的申明為sealed,阻止發生派生,而派生可能會增加實例
2、實例變量申明為readonly,這個是關鍵點(readonly為運行時常量)。
第一次運行,會在全局的靜態存儲區域中初始化,因為是readonly的,所以就只會初始化一次,以后不會在變。
這中方案的缺點是:對實例化機制的控制權較少,就是說你沒有調用實例,但實例對象已經生成。(我覺得無所謂)
3、我覺得不需要第二構造函數,不知道為啥,李大牛(http://m.survivalescaperooms.com/Terrylee/archive/2005/12/09/293509.html)的設計模式中添加了第二個構造函數。
期待大家解惑(不寫,默認就是啊)。
看完湯姆叔的http://m.survivalescaperooms.com/TomXu/archive/2011/12/19/2291448.html博客(慚愧),解惑。
延遲初始化實例:
public sealed class Singleton{ private Singleton() { } public static Singleton Instance { get { return Nested.instance; } } private class Nested { static Nested() { } internal static readonly Singleton instance = new Singleton(); }}
對代碼的理解:
1、這段代碼與《運行時實例》的區別就是,只有在你調用時,才會在生成實例到全局的靜態存儲區域中。
應用的場景:
我使用Microsoft.Practices.Unity容器在config中配置了依賴注入的實現,那么我需要去讀取這些配置,
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <alias alias="" type="" /> <alias alias="" type="" /> <container name="XXXAdapter"> </container> <container name="YYYAdapter"> </container></unity>
internal sealed class InitContainer{ private static IUnityContainer container; private static readonly object _lock = new object(); private InitContainer() { } public static IUnityContainer GetInstance() { if (container == null) { lock (_lock) { if (container == null) { container = new UnityContainer(); //獲取指定名稱的配置節 UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); container.LoadConfiguration(section, ""); container.LoadConfiguration(section, ""); } } } return container; }}
這樣就保證只讀取一次的配置信息
新聞熱點
疑難解答