乙個類只允許建立唯一乙個物件(或者例項),那這個類就是乙個單例類,這種設計模式就叫作單例設計模式,簡稱單例模式。
經典的設計模式有 23 種, 如果隨便抓乙個程式設計師,讓他說一說最熟悉的 3 種設計模式,那其中肯定會包含今天要講的單例模式,
單例模式主要用來確保某個型別的例項只能有乙個。比如手機上的藍芽之類的只能有乙個的例項的場景可以考慮用單例模式。
主要作用:
單例模式的實現,通常需要私有化構造方法,防止外部類直接使用單例類的構造方法建立物件
public class singleton
public static singleton getinstance()
return _instance;}}
這種方式比較簡單,但是不是執行緒安全的,多執行緒高併發情況下可能會導致建立多個例項,但是如果你的業務場景允許建立多個,我覺得問題也不大,如果一定要保證只能建立乙個例項,可以參考下面的做法
/// /// 雙重判空加鎖,飽漢模式(懶漢式),用到的時候再去例項化
///
public class singleton
public static singleton getinstance()}}
return _instance;}}
這種方式的執行過程會先檢查是否完成了例項化,如果已經例項化則直接返回例項,如果沒有就嘗試獲取鎖,獲得鎖之後再判斷一下是否已經例項化,如果已經例項化則返回例項,如果沒有就進行例項化
/// /// 餓漢模式-就是屌絲,擔心餓死。類載入就給準備好
///
public sealed class singleton1
public static singleton1 getinstance() => instance;
}
這也是一種常見的實現單例模式的用法,但是這種方式就不支援懶載入了,不像上面那種方式可以做到需要的時候再例項化,適用於這個物件會被頻繁使用或者這個模擬較小,是否例項化沒有什麼影響。
這個是之前忘記在**看到的微軟框架裡的一段**,類似,可能和原始碼並不完全一樣,只是提供一種實現思路
/// /// 使用 concurrentdictionary 實現的單例方法,用到的時候再去例項化
/// 這種方式類似於第一種方式,只是使用了併發集合代替了雙重判斷和 lock
///
public class singleton2
public static singleton2 getinstance() => instances.getoradd(1, k => new singleton2());
}
c# 裡提供了lazy
的方式實現延遲例項化
/// /// 使用 lazy 實現的單例方法,用到的時候再去例項化
///
public class singleton3
public static singleton3 getinstance() => lazyinstance.value;
}
驗證是否執行緒安全,驗證示例**:
console.writeline($"singleton");
enumerable.range(1, 10).select(i => task.run(() =>
");})).whenall().wait();
console.writeline($"singleton1");
enumerable.range(1, 10).select(i => task.run(() =>
");})).whenall().wait();
console.writeline($"singleton2");
enumerable.range(1, 10).select(i => task.run(() =>
");})).whenall().wait();
console.writeline($"singleton3");
enumerable.range(1, 10).select(i => task.run(() =>
");})).whenall().wait();
上面的whenall
是乙個擴充套件方法,就是呼叫的task.whenall
,輸出示例:
隨著現在依賴注入思想的普及,asp.net core 更是基於依賴框架構建的,使用依賴注入的方式可以較好的解決上面的各種問題
基於依賴注入框架,你可以不必擔心物件的建立和銷毀,讓依賴注入框架管理物件,這樣這個要實現單例模式的型別可以和其他普通型別一樣,只需要使用依賴注入框架註冊服務的時候指定服務生命週期為單例即可,比如使用微軟的依賴注入框架的時候可以使用services.addsingleton();
來註冊單例服務
關於使用雙檢鎖實現單例的時候是否要使用volatile
的問題,在 c# 如果你使用了lock
就沒有必要再去用volatile
標記要同步的物件了,
volatile
的主要是用在於解決多個cpu上執行的多個執行緒可以並且將快取資料和指令重新排序的問題。
如果它不是volatile
的,並且cpu a遞增了乙個值,則cpu b可能直到一段時間後才能真正看到該遞增的值,這可能會引起問題。
如果它是volatile
的,則僅確保兩個cpu同時看到相同的資料。 它根本不會阻止他們交錯讀取和寫入操作,而這正是您要避免的問題。
使用lock
也可以防止上述多cpu重新排序問題,所以使用了lock
就可以不需要再volatile
了
設計模式之單例模式
前一段時間買了一本秦小波寫的 設計模式之禪 網上對這書的評價很高。現在還沒有看很多,但是有些地方頗有感觸,也並不是所有的地方都能看懂,但是會慢慢研究的。自己對於設計模式的感覺就是乙個字 牛!感覺會23種設計模式並且會熟練運用的人,真的就是大師級的牛人了,設計模式是乙個專案主管或者架構師一定要會的東西...
設計模式之單例模式
package com.xie.singleton public class singleton 提供乙個共有的靜態的入口方法 public static singleton getinstance 懶漢式 延遲載入 提供乙個私有的靜態的成員變數,但不做初始化 private static sing...
設計模式之 單例模式
單例模式 singleton 保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。單例模式 單件模式 使用方法返回唯一的例項 public class singleton private static singleton instance public static singleton geti...