1. 程式人生 > >單例模式及常見寫法分析(設計模式01)

單例模式及常見寫法分析(設計模式01)

啟動 nes 成員變量 額外 log 序列 spa tar adl

保證一個類僅有一個實例。並提供一個該實例的全局訪問點。

——《設計模式》

單例模式的概念非常easy。以下以C#語言為樣例,列出常見單例寫法的優缺點。

1、簡單實現

 public sealed class Singleton
    {
        static Singleton instance = null;

        public void Show()
        {
            Console.WriteLine(  "instance function");
        }
        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
評註:

對於線程來說不安全
單線程中已滿足要求
長處:
由於實例是在 Instance 屬性方法內部創建的。因此類能夠使用附加功能
直到對象要求產生一個實例才執行實例化;這樣的方法稱為“惰性實例化”。

惰性實例化避免了在應用程序啟動時實例化不必要的 singleton。

2、線程的安全

public sealed class Singleton
    {
        static Singleton instance = null;
        private static readonly object padlock = new object();

        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }

                return instance;
            }
        }
    }


評註:

同一個時刻加了鎖的那部分程序僅僅有一個線程能夠進入
對象實例由最先進入的那個線程創建
後來的線程在進入時(instence == null)為假,不會再去創建對象實例
添加了額外的開銷,損失了性能


3、雙重鎖定

 public sealed class Singleton
    {
        static Singleton instance = null;
        private static readonly object padlock = new object();

        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }
評註:

多線程安全
線程不是每次都加鎖
同意實例化延遲到第一次訪問對象時發生


4、靜態初始化

 public sealed class Singleton
    {
        private static readonly Singleton instance = null;
        static Singleton()
        {
            instance = new Singleton();
        }
        private Singleton()
        {
        }
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }
評註:

依賴公共語言執行庫負責處理變量初始化
公共靜態屬性為訪問實例提供了一個全局訪問點
對實例化機制的控制權較少(.NET代為實現)
靜態初始化是在 .NET 中實現 Singleton 的首選方法

小註:

靜態構造函數既沒有訪問修飾符,C#會自己主動把他們標記為private。之所以必須標記為private。

是為了阻止開發者寫的代碼調用它,對它的調用總是由CLR負責的。


技術分享
技術分享

技術分享


5、延遲初始化

public sealed class Singleton
    {
        private Singleton()
        {
        }
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        public static void Hello()
        {
        }

        private class Nested
        {
            internal static readonly Singleton instance = null;
            static Nested()
            {
                instance = new Singleton();
            }
        }
    }
評註:

初始化工作由Nested類的一個靜態成員來完畢,這樣就實現了延遲初始化。

由於靜態函數的調用時機,是在類被實例化或者靜態成員被調用的時候進行調用。並且是由.net框架來調用靜態構造函數來初始化靜態成員變量。 所以,假設依照寫法四來寫。再調用Hello方法的時候,就會實例化出來Singleton實例,這不是我們想看到的。由於我們有可能僅僅是想用Hello方法,而不是別的。


註意事項:

1、Singleton模式中的實例構造器能夠設置為protected以同意子類派生。
2、Singleton模式一般不要支持ICloneable接口,由於這可能會導致多個對象實例,與Singleton模式的初衷違背。


3、Singleton模式一般不要支持序列化,由於這也有可能導致多個對象實例,相同與Singleton模式的初衷違背。
4、Singletom模式僅僅考慮到了對象創建的管理,沒有考慮對象銷毀的管理。就支持垃圾回收的平臺和對象的開銷來講,我們一般沒有必要對其銷毀進行特殊的管理。


總結:

1、Singleton模式是限制而不是改進類的創建。
2、理解和擴展Singleton模式的核心是“怎樣控制用戶使用new對一個類的構造器的隨意調用”。
3、能夠非常easy的改動一個Singleton,使它有少數幾個實例。這樣做是同意的並且是有意義的。


作者:jiankunking 出處:http://blog.csdn.net/jiankunking


本文部分內容來自網絡,截圖部分來自《CLR.via.C#第三版》




單例模式及常見寫法分析(設計模式01)