軟件設計模式之單例模式

單例模式的概念:

單例模式保證一個類只有一個實例,並且提供一個訪問它的全局訪問點;

單例模式存在的意義:

單例模式用於當我們系統中的某個對象只需要一個實例的情況;例如PC遠程桌面只能有一個人進行操作一個用戶;

實現思路:

(1)、需要確保一個類只有一個實例

    創建公有類、私有構造函數實現;

    

   public class Singleton
    {
        //私有變量來記錄Singleton的唯一實例
        private static Singleton singleton;
        //私有構造函數
        private Singleton()
        {
        }
    }    

  

(2)、提供一個訪問他的全局訪問點

  (2.1)、加鎖

  (2.2)、雙重鎖定

        //定義共有方法來提供該類的唯一全局訪問點
        public static Singleton GetInstance()
        {
            /*當第一個線程運行到這裡時,此時會對locker對象「加鎖」
             * 當第二個線程運行該方法時,首先檢測到locker對象為「加鎖狀態」,該線程就會掛        
              起等待第一個線程解鎖
             * lock語句運行完之後(即線程運行完之後)會對該對象解鎖
             * 雙重鎖定只需要一句判斷就可以
             * **/
            if (singleton == null)
            {
                lock (locker)
                {
                    //判斷該實例是否存在,不存在則new一個新實例,否則返回已有實例
                    if (singleton == null)
                    {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }         

 

總結:

公有類、私有構造函數、全局訪問點(判斷、加鎖、判斷)

 

完整源碼:

   public class Singleton
    {
        //私有變量來記錄Singleton的唯一實例
        private static Singleton singleton;

        //定義一個標識確保線程同步
        private static readonly object locker = new object();

        //私有構造函數
        private Singleton()
        {
        }

      /// <summary>
      /// 定義共有方法來提供該類的唯一全局訪問點
      /// </summary>
      /// <returns>實例化對象</returns>

        public static Singleton GetInstance()
        {
            /*當第一個線程運行到這裡時,此時會對locker對象「加鎖」
             * 當第二個線程運行該方法時,首先檢測到locker對象為「加鎖狀態」,該線程就會掛起等待第一個線程解鎖
             * lock語句運行完之後(即線程運行完之後)會對該對象解鎖
             * 雙重鎖定只需要一句判斷就可以
             * **/
            if (singleton == null)
            {
                lock (locker)
                {
                    //判斷該實例是否存在,不存在則new一個新實例,否則返回已有實例
                    if (singleton == null)
                    {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    } 

 

 

測試:

OK,實現已經結束了,現在來測試下單例模式的效果;

首先在單例模式類中定義一個測試用的字符串

        //測試單例模式效果
        private string strTest;

        public string StrTest { get => strTest; set => strTest = value; }

然後設計測試代碼:

        static void Main(string[] args)
        {
            Singleton singleton = Singleton.GetInstance();
            singleton.StrTest = "test";
            Console.WriteLine(singleton.StrTest);
            TestSingleton();
        }

        private static void TestSingleton()
        {
            Singleton singleton = Singleton.GetInstance();
            Console.WriteLine(singleton.StrTest);
        }

  

按照非單例模式上列代碼執行結果應該是先顯示test,然後顯示空串

測試代碼:

        static void Main(string[] args)
        {
            Test test = new Test();
            test.StrTest = "test";
            Console.WriteLine(test.StrTest);
       TestSingleton(); } private static void TestSingleton() { Test test = new Test(); Console.WriteLine(test.StrTest); }

  

測試結果:

 

運行單例模式測試代碼測試結果如下:

 

根據上面測試的結果可以知道,無論是重新多少次調用入口,它永遠只會讓你訪問那一個實例!