軟件設計模式之單例模式
單例模式的概念:
單例模式保證一個類只有一個實例,並且提供一個訪問它的全局訪問點;
單例模式存在的意義:
單例模式用於當我們系統中的某個對象只需要一個實例的情況;例如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); }
測試結果:
運行單例模式測試代碼測試結果如下:
根據上面測試的結果可以知道,無論是重新多少次調用入口,它永遠只會讓你訪問那一個實例!