單件模式學習總結(創建型)

  學習設計模式。在這裏很感激:TerryLee 。在看了這位大哥的blog,對設計模式有所瞭解。大家可以去看看。寫得確實不錯哦。我現在在這裏也是剽竊大哥的心血,不過這是我的學習,權當是讀書筆記了。

  單件模式的概念和用途:  

Singleton模式要求一個類有且僅有一個實例,並且提供了一個全局的訪問點。這就提出了一個問題:如何繞過常規的構造器,提供一種機制來保證一個類只有一個實例?客戶程序在調用某一個類時,它是不會考慮這個類是否只能有一個實例等問題的,所以,這應該是類設計者的責任,而不是類使用者的責任。 在現實中,單點登錄:在某個系統運行中,只有單個當前用戶。
單件模式實現的幾種模式:
1.普遍簡單的寫法,這種寫法只是簡單的考慮實現,是一種雛形。可以說是最直觀的:要將一個類不能用new實例化。
public sealed class Singleton
 {
     static Singleton instance=null;
 
     Singleton()
     {
     }
 
     public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}
     在多線程下存在不安全:在多線程的環境下有可能得到Singleton類的多個實例。如果同時有兩個線程去判斷(instance == null),並且得到的結果爲真,這時兩個線程都會創建類Singleton的實例,這樣就違背了Singleton模式的原則。實際上在上述代碼中,有可能在計算出表達式的值之前,對象實例已經被創建,但是內存模型並不能保證對象實例在第二個線程創建之前被發現。

    優點:
  
l         由於實例是在 Instance 屬性方法內部創建的,因此類可以使用附加功能(例如,對子類進行實例化),即使它可能引入不想要的依賴性。
l         直到對象要求產生一個實例才執行實例化;這種方法稱爲“惰性實例化”。惰性實例化避免了在應用程序啓動時實例化不必要的 singleton
2  安全的考慮(在多線程下)
public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();
    Singleton()
    {
    }
    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                   instance = new Singleton();
                }
                return instance;
            }
        }
    }
}
     首先創建了一個進程輔助對象,線程在進入時先對輔助對象加鎖然後再檢測對象是否被創建,這樣可以確保只有一個實例被創建,因爲在同一個時刻加了鎖的那部分程序只有一個線程可以進入。這種情況下,對象實例由最先進入的那個線程創建,後來的線程在進入時(instence == null)爲假,不會再去創建對象實例了。但是這種實現方式增加了額外的開銷,損失了性能。

主要適用了lock的方法,保證共享對象的同步。
3.雙重鎖定
    public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();
    Singleton()
    {
    }
    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                lock (padlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}
這種實現方式對多線程來說是安全的,同時線程不是每次都加鎖,只有判斷對象實例沒有被創建時它才加鎖,有了我們上面第一部分的裏面的分析,我們知道,加鎖後還得再進行對象是否已被創建的判斷。它解決了線程併發問題,同時避免在每個 Instance 屬性方法的調用中都出現獨佔鎖定。它還允許您將實例化延遲到第一次訪問對象時發生。實際上,應用程序很少需要這種類型的實現。大多數情況下我們會用靜態初始化。這種方式仍然有很多缺點:無法實現延遲初始化。

4.靜態初始化 
public sealed class Singleton
{
    static readonly Singleton instance=new Singleton();
    static Singleton()
    {
    }
    Singleton()
    {
    }
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}
在此實現中,將在第一次引用類的任何成員時創建實例。公共語言運行庫負責處理變量初始化。該類標記爲 sealed 以阻止發生派生,而派生可能會增加實例。此外,變量標記爲 readonly,這意味着只能在靜態初始化期間(此處顯示的示例)或在類構造函數中分配變量。
該實現與前面的示例類似,不同之處在於它依賴公共語言運行庫來初始化變量。它仍然可以用來解決 Singleton 模式試圖解決的兩個基本問題:全局訪問和實例化控制。公共靜態屬性爲訪問實例提供了一個全局訪問點。此外,由於構造函數是私有的,因此不能在類本身以外實例化 Singleton 類;因此,變量引用的是可以在系統中存在的唯一的實例。
由於 Singleton 實例被私有靜態成員變量引用,因此在類首次被對 Instance 屬性的調用所引用之前,不會發生實例化。
這種方法唯一的潛在缺點是,您對實例化機制的控制權較少。在 Design Patterns形式中,您能夠在實例化之前使用非默認的構造函數或執行其他任務。由於在此解決方案中由 .NET Framework 負責執行初始化,因此您沒有這些選項。在大多數情況下,靜態初始化是在 .NET 中實現 Singleton 的首選方法。
5.延遲初始 
public sealed class Singleton
{
    Singleton()
    {
    }
    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }
   
    class Nested
    {
        static Nested()
       {
        }
        internal static readonly Singleton instance = new Singleton();
    }
}
初始化工作有Nested類的一個靜態成員來完成,這樣就實現了延遲初始化,並具有很多的優勢。

要點

l        Singleton模式是限制而不是改進類的創建。

 

 

l         可以很簡單的修改一個Singleton,使它有少數幾個實例,這樣做是允許的而且是有意義的

優點

l         實例控制:Singleton 會阻止其他對象實例化其自己的 Singleton 對象的副本,從而確保所有對象都訪問唯一實例

l         靈活性:因爲類控制了實例化過程,所以類可以更加靈活修改實例化過程

缺點

l         開銷:雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題,上面的五種實現方式中已經說過了。

l          可能的開發混淆:使用 singleton 對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用 new 關鍵字實例化對象。因爲可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。

l         對象的生存期:Singleton 不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基於 .NET Framework 的語言),只有 Singleton 類能夠導致實例被取消分配,因爲它包含對該實例的私有引用。在某些語言中(如 C++),其他類可以刪除
對象實例,但這樣會導致 Singleton 類中出現懸浮引用。

適用性

l         當類只能有一個實例而且客戶可以從一個衆所周知的訪問點訪問它時。

l         當這個唯一實例應該是通過子類化可擴展的,並且客戶應該無需更改代碼就能使用一個擴展的實例時。

 

再次提醒:感恩。http://terrylee.cnblogs.com/archive/2006/06/01/334911.html

 

l         Singleton類中的實例構造器可以設置爲Protected以允許子類派生。

l         Singleton模式一般不要支持Icloneable接口,因爲這可能導致多個對象實例,與Singleton模式的初衷違背。

l         Singleton模式一般不要支持序列化,這也有可能導致多個對象實例,這也與Singleton模式的初衷違背。

l         Singleton只考慮了對象創建的管理,沒有考慮到銷燬的管理,就支持垃圾回收的平臺和對象的開銷來講,我們一般沒必要對其銷燬進行特殊的管理。

l         理解和擴展Singleton模式的核心是“如何控制用戶使用new對一個類的構造器的任意調用”。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章