什麼事邊角料? 邊角料就是你編程的時候,很少能夠用上,或者說你壓根就不知道得東西,我就稱這些東西為邊角料。這個叫.net邊角料可能有點大,其實這個系列是純粹的C#邊角料系列。 為什麼寫.net邊角料呢,因為.net coder越來越少了,所以邊角的東西,知道的人也越來越少,雖然價值不大,但是要抱著拋 ...
- 什麼事邊角料?
邊角料就是你編程的時候,很少能夠用上,或者說你壓根就不知道得東西,我就稱這些東西為邊角料。這個叫.net邊角料可能有點大,其實這個系列是純粹的C#邊角料系列。
為什麼寫.net邊角料呢,因為.net coder越來越少了,所以邊角的東西,知道的人也越來越少,雖然價值不大,但是要抱著拋磚引玉的思想,把更多的人留在.net上,助力.net core紅紅火火大發展——之後我好轉其他語言。就是這種拉一個人下水是一個,倆個人下水賺一個的精神支持著我,希望我能把.net邊角料系列寫完。我不是代碼的生產者,只是代碼的搬運工,所以對於邊角料出現的代碼如果有開源代碼地址,我一定會將開源代碼位置附上,以供下水者沉迷其中,不能自拔。
- 邊角料的單例模式
如果說單例模式是邊角料,估計我會挨噴,基本每次面試都可能被問到,而且不懂單例模式,好意思說自己是一個.net程式員嗎?所以咱們這談的不是傳統的單例模式,更不會談什麼線程安全性,以及懶載入、惰性載入的問題。
不過也得問一句,單例模式符合設計模式的六大原則嗎?至少單一職責原則,它不符合。它既要保證自己單例又要保證自己原有意義。設計模式上沒有什麼是拆分辦不到的,如果辦不到,那就再拆分一次。
所以下麵我們正式介紹我們的邊角料——泛型單例
- 源碼及地址
沒有什麼比源碼更有說服力了,首先上源碼地址:nopCommerce(https://github.com/nopSolutions/nopCommerce)這個是大名鼎鼎的nopCommerce,具體它有多牛,自行百度,反正我也不知道。類文件叫做:Singleton.cs
1 public class Singleton<T> : Singleton 2 { 3 static T instance; 4 public static T Instance 5 { 6 get { return instance; } 7 set 8 { 9 instance = value; 10 AllSingletons[typeof(T)] = value; 11 } 12 } 13 } 14 15 public class SingletonList<T> : Singleton<IList<T>> 16 { 17 static SingletonList() 18 { 19 Singleton<IList<T>>.Instance = new List<T>(); 20 } 21 public new static IList<T> Instance 22 { 23 get { return Singleton<IList<T>>.Instance; } 24 } 25 } 26 27 public class SingletonDictionary<TKey, TValue> : Singleton<IDictionary<TKey, TValue>> 28 { 29 static SingletonDictionary() 30 { 31 Singleton<Dictionary<TKey, TValue>>.Instance = new Dictionary<TKey, TValue>(); 32 } 33 34 public new static IDictionary<TKey, TValue> Instance 35 { 36 get { return Singleton<Dictionary<TKey, TValue>>.Instance; } 37 } 38 } 39 40 41 public class Singleton 42 { 43 static Singleton() 44 { 45 allSingletons = new Dictionary<Type, object>(); 46 } 47 48 static readonly IDictionary<Type, object> allSingletons; 49 50 public static IDictionary<Type, object> AllSingletons 51 { 52 get { return allSingletons; } 53 } 54 }
- 代碼分析
單例模式就是設計模式最最簡單的了,泛型單例也是簡單到令人髮指。代碼分析有什麼說的呢,不過為了湊篇幅,強說兩句吧。
1.這裡面一共有四個類:Singleton、Singleton<T>、SingletonList<T>、SingletonDictionary<TKey, TValue>。繼承關係是Singleton<T>集成自Singleton,而SingletonList<T>、SingletonDictionary<TKey, TValue>繼承自Singleton<T>.
對於不熟悉泛型的同學來說,我可以拍胸脯的告訴你,泛型類可以繼承自非泛型類,非泛型類可以繼承自泛型類,只要你想沒啥不可以的。
2.對於這四個類,所有內容都是靜態的——構造函數、欄位、屬性。對於靜態構造函數,這個和普通構造函數不同的地方有三:首先它只用於初始化靜態變數,其次靜態構造函數不供其他類調用(所以不能用public、private修飾),只夠clr初始化的時候調用。最後靜態構造函數不能有參數列表,因為沒人能給它傳參。
3.對於泛型來說,List<int>和List<string>是倆個完全不同的類,所以儘管SingletonList<T>只有一個靜態變數,但是對於已經非泛化(具體類型代入後)的各個類型,都有自己的靜態變數,所以每個T類型都對應SingletonList<T>的Instance屬性,所以泛型類能夠保證每個實例都能是全局唯一——也就是單例模式。
4.對於Singleton非泛型類,他唯一的作用就是提供一個集合,供其他對象檢索,哪些類型已經被泛型單例類緩存了。這完全不是必須的。但是他給我們提了一個醒:對於非泛型類每個類單獨所有的靜態變數,要放到泛型類的父類中。換句話說,就是泛型類出現靜態變數要慎重,是不是要放到父類中。
- 實用的代碼
泛型單例這段源碼,雖然高大上,但是不一定符合我們的要求,所以我們有時候有實用的要求,下麵就供上我簡化的泛型單例源碼.
public class Singleton<T> where T:new() { static T instance=new T(); public static T Instance { get { return instance; } set { instance = value; } } }
- 說到最後
雖然泛型單例確實是邊角料,但是泛型、靜態構造函數、以及nopCommerce絕對不是邊角料。願這些似是而非的邊角料,對你有益。