1. 程式人生 > >C#設計模式04-單例模式

C#設計模式04-單例模式

        昨天給大家介紹了原型模式,今天給大家介紹的是單例模式,也是最簡單的一種建立型模式。

        在我們的軟體系統中,有時候保持一個類只有一個例項是非常重要的。比如說,作業系統中的工作管理員,只能有一個視窗,也就是說它在系統中只能有一個例項,否則就會彈出多個工作管理員視窗。再比如說,系統中的印表機,同一時間只能執行一個列印任務,如果有多個印表機例項,那麼同一時間可以列印多個任務,這會導致列印結果發生混亂。因此,軟體開發中,有時候保持一個類只有一個例項是非常重要的。

        先看單例模式的定義:確保一個類只有一個例項,並提供一個全域性訪問點來訪問這個唯一例項。

        那麼如何確保一個類只有一個例項並且可以被外部訪問呢?從定義上看有三點:一是一個類只能有一個例項,而是它必須自己建立這個例項(這樣可以防止外部對它例項化),三是它必須提供一個全域性的訪問點(靜態全域性變數)。

        單例模式的角色非常簡單,只有一個單例類

        那麼該如何實現單例模式呢?請看下面的程式碼

namespace 單例模式
{
    public class Singleton
    {
        //第二步:提供一個全域性訪問點,外部通過這個訪問點訪問例項
        private static Singleton instance = null;
        //第一步:將建構函式宣告為Private,可以防止外部對該物件進行例項化
        private Singleton() { }
        //第三步:單例類本身負責建立例項
        public static Singleton GetInstance()
        {
            if (instance == null)
                instance = new Singleton();
            return instance;
        }
    }
}
namespace 單例模式
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton s1 = Singleton.GetInstance();
            Singleton s2 = Singleton.GetInstance();
            if (s1 == s2)
            {
                Console.Write("s1和s2是同一個例項!");
            }
            else
            {
                Console.Write("s1和s2不是同一個例項!");
            }
            Console.ReadLine();
        }
    }
}
程式碼中單例模式的實現步驟已經寫得很清楚,這裡就不在作解釋了。下面看看執行結果

執行結果顯示s1和s2是同一個例項,說明外部物件拿到的是Singleton的同一個例項。

上面的實現方法是單例模式最簡單的實現方法。

接下來來介紹兩種不同實現方法的單例模式,餓漢式單例和懶漢式單例。

先來看看餓漢式單例類的程式碼。

namespace 單例模式
{
    
    public class Singleton 
    {
        private static Singleton instance = new Singleton();
        private Singleton() { }
        public static Singleton GetInstance()
        {
            return instance;
        }
    }
}
當類被載入的時候,靜態變數instance就會被初始化,然後建立單例類的例項。

然後我們來看看懶漢式單例模式的程式碼,懶漢式和餓漢式的建構函式都是私有的,不同的是懶漢式單例類不會在類載入時初始化單例類,而是在呼叫靜態工廠方法的時候例項化單例類。來看看下面的程式碼。

public class Singleton
    {
        private static Singleton instance = null;
        private static readonly object lockObject = new object();
        private Singleton() { }
        public static Singleton GetInstance()
        {
            //第一次判斷
            if (instance == null)
            {
                //加鎖,防止同一時刻多個執行緒同時訪問,導致例項化多個物件
                lock (lockObject)
                {
                    //第二次判斷
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
在程式碼中使用了Lock關鍵字對指定程式碼片段上鎖,防止同一時刻多個執行緒同時訪問單例類,最後導致系統的例項不是一個,而是多個。

程式碼中兩次判斷instance==null,是必不可少的。假如說兩個執行緒同時通過第一次判斷,第一個執行緒進入lock程式碼片段後,判斷instance還是為空,就例項化。如果第二個執行緒進來我們不判斷的話,它還會繼續例項化單例類。

下一篇文章將給大家介紹建立型模式中的最後一種—-建造者模式。