單例子模式定義 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點. 通常我們可以讓一個全局變數使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是讓類自身負責保存它的唯一實例。這個類可以保證沒有其它實例可以唄創建並且它可以提供一個訪問該實例的方法,這就是單例模式。 單例子模式簡單 ...
單例子模式定義
保證一個類僅有一個實例,並提供一個訪問它的全局訪問點.
通常我們可以讓一個全局變數使得一個對象被訪問,但它不能防止你實例化多個對象。一個最好的辦法就是讓類自身負責保存它的唯一實例。這個類可以保證沒有其它實例可以唄創建並且它可以提供一個訪問該實例的方法,這就是單例模式。
單例子模式簡單實現
Singleton類定義了一個GetInstance 操作,允許客戶訪問它的唯一實例,GetInstance是一個靜態方法,主要負責創建自己的唯一實例。
public class Singleton { private static Singleton _instance; private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來創建實例 {} public static Singleton GetInstance() { return _instance ?? (_instance = new Singleton()); } }
測試代碼
public void Myaction() { var s1 = Singleton.GetInstance(); var s2 = Singleton.GetInstance(); if (s1 == s2) { Console.WriteLine("兩個對象是相同的!"); } Console.Read(); }
多線程時的單例
上面的代碼在多線程的程式下運行明細是有問題的,當多個線程同時訪問Singleton類 都調用GetInstance()方法,就有可能會創建多個實例。
這種情況我們可以給進程一把鎖來處理,這裡需要理解 lock 語句的涵義,lock 是確保當前一個線程位於代碼的臨界區時,另一個線程不進入臨界區。如果其它線程試圖進入鎖定的代碼,則它將一直等待(即被阻止),直到該對象被釋放。
簡單實現
public class Singleton { private static Singleton _instance; //程式執行時創建一個靜態的只讀的進程輔助對象 private static readonly object SyncRoot = new object(); private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來創建實例 { } public static Singleton GetInstance() { lock (SyncRoot)//在同一時刻加了鎖的那部分程式只有一個線程可以進入 { _instance= _instance ?? (_instance = new Singleton()); } return _instance; } }
雙重鎖定(Double-Check Locking)
通過上面的例子我們不難發現當我們每次調用 GetInstance() 方法時都要 lock 這種做法顯然是影響性能的所以我們需要再加一層判斷
簡單實現
public class Singleton { private static Singleton _instance; //程式執行時創建一個靜態的只讀的進程輔助對象 private static readonly object SyncRoot = new object(); private Singleton()//私有化構造函數,阻止外界利用new關鍵詞來創建實例 {} public static Singleton GetInstance() { if (_instance == null)//先判斷實例是否存在,不存在在枷鎖處理 { lock (SyncRoot)//在同一時刻加了鎖的那部分程式只有一個線程可以進入 { _instance = _instance ?? (_instance = new Singleton()); } } return _instance; } }
工廠單例創建數據上下文
我們在開發過程中經常都需要對數據上下文進行單例,所以這裡結合簡單工廠 來實現數據上下文的創建
簡單實現
public class DbFactory { private static readonly object SyncRoot=new object(); private DbFactory() {} #region 獲取當前的上下文對象 /// <summary> /// 單例工廠 獲取當前的上下文對象 //考慮多線程情況 /// </summary> /// <returns></returns> public static SiyoukuContext GetCurrentDbContext() { var context = (SiyoukuContext) CallContext.GetData("DbContext"); //從數據槽獲取 if (context == null) { lock (SyncRoot)//雙重鎖定 { if (context == null) { //如果不存在 ,則實例化一個上下文對象 context = new SiyoukuContext(); CallContext.SetData("DbContext", context); } } } return context; } #endregion }
本文記錄了自己對單例模式的總結
本文永久更細地址:http://siyouku.cn/article/6812.html