[設計模式]SingletonPattern

文藝小青年發表於2017-11-22

 前些天有人面試碰到了這個東東,可能下次我換工作時說不定也會碰到,這個東東可是人見人愛,有講設計模式肯定會被問到的一個模式。所以也就順便看看,寫寫,這篇文章的主要來源是老外寫的《Implementing the Singleton Pattern in C#》,半譯半寫就是這樣。沒有什麼特別的,不過不知道國內有沒有人翻譯過此文,不管3721我們開始吧。

  由於我沒有系統的學過設計模式,也沒有人教我所以碰到了就順便看一看的,在講Singleton設計模式之前當然我們要知道什麼時候才使用到這個模式,什麼時候我們最好不要用這個設計模式,不然學這個有什麼用呢?不知道大家是怎麼想的,下面我們來看看到底什麼時候我們才使用Singleton模式,使用該模式的必要條件就是在一個系統中一個類有且只有一個例項;相反就不能使用Singleton模式。但要注意的是我們不要用Singleton模式來存取全域性變數,這違背了Singleton模式的用意;同時我們也不要用Singleton模式來做資料庫的聯接,這樣會浪費太多的資源,因為不能及時的釋放資源。

  從上面我們可以知道Singleton模式的特點:一個Singleton模式類要通過自己來例項化自己,並且不能在其它地方被例項化,所以必需要有一個沒有帶引數的Private構造(確保不能用new來例項化)和帶sealed的類(確保不能被繼承);需要一個靜態方法得到自身類的例項物件。下面我們來看看在C#中實現Singleton模式的幾種方法,在後面回加以說明(注:例子來自《Implementing the Singleton Pattern in C#)

   Singleton

{

     Singleton instance=;

 

    Singleton()

    {

    }

 

      Singleton Instance

    {

        get

        {

             (instance==)

            {

                instance =  Singleton();

            }

             instance;

        }

    }

}

  以上是實現Singleton模式的第一種方法,這種方法不是執行緒安全的,也就是說在兩個不同的執行緒中有可能在同一時間建立物件,即建立了兩個不同的例項物件,這就違背了Singleton模式,因此這種方法是不提倡的。

   Singleton

{

     Singleton instance=;

       padlock =  ();

 

    Singleton()

    {

    }

 

      Singleton Instance

    {

        get

        {

             (padlock)

            {

                 (instance==)

                {

                    instance =  Singleton();

                }

                 instance;

            }

        }

    }

}

  這種方法是執行緒安全的,通過鎖定一個共享物件,因為在建立物件時先鎖定了一個物件。例如在兩個類中都呼叫了這個Instance屬性,當第一個呼叫時先將padlock物件鎖定了,則第二個呼叫類就只能等到這個物件解鎖以後才能進行。然後再判斷是否已經建立了這個物件,如果沒有建立則建立此物件。雖然線上程上是安全的,但是每次呼叫時都會有一個鎖定的過程這樣就會消耗一定的資源,也就是說效能上有點問題!

   Singleton

{

     Singleton instance=;

       padlock =  ();

 

    Singleton()

    {

    }

 

      Singleton Instance

    {

        get

        {

             (instance==)

            {

                 (padlock)

                {

                     (instance==)

                    {

                        instance =  Singleton();

                    }

                }

            }

             instance;

        }

    }

}

  以上例子似乎是執行緒安全的,但是它在JAVA.NET下都會出現問題,由於我對JAVA不熟悉所以英文當然就看的比較模糊,應該是說記憶體邊界(memory barrier我也不知道對不對)會出現問題;在.NET中這種做法無法實現延遲初始化,總之這種做法是不推薦的。(等我知道怎麼回事了再補上吧!或是哪位能給予指導,謝謝!)

public sealed class Singleton

{

    static readonly Singleton instance=new Singleton();

 

    // Explicit static constructor to tell C# compiler

    // not to mark type as beforefieldinit

    static Singleton()

    {

    }

 

    Singleton()

    {

    }

 

    public static Singleton Instance

    {

        get

        {

            return instance;

        }

    }

}

  通過靜態構造來實現Sigleton設計模式,在大多數情況下我們都會採用這種來實現Sigleton設計模式。在C#中靜態建構函式只會在一個物件被初始化或一個靜態成員被引用時執行,並且在整個程式域中只執行一次。變數標記為 readonly,這意味著只能在靜態初始化期間,該變數的值就是固定不變的了,所以也就不可能再初始化物件了。也就是說不初始化了一次,也就是Sigleton設計模式,並且保證執行緒安全。

   Singleton

{

    Singleton()

    {

    }

 

      Singleton Instance

    {

        get

        {

             Nested.instance;

        }

    }

    

     Nested

    {

        

        

         Nested()

        {

        }

 

           Singleton instance =  Singleton();

    }

}

  這種做法實現了延遲例項化,因此這也是一種不錯的選擇。基本上Sigleton設計模式就這5種實現方法,而最值的推薦的是第4種方法,程式碼簡單而又不失效能。


本文轉自網魂小兵部落格園部落格,原文連結:http://www.cnblogs.com/xdotnet/archive/2007/01/07/pattern_sigleton.html,如需轉載請自行聯絡原作者


相關文章