標籤:
先來看看Singleton的使用案例圖:
在一個實際的老項目中,有很多的業務類,也不知道當時如何設計的,這些業務類均被設計成了Singleton模式。
項目中這些業務類結構如下:
而每個業務類的設計均為單例,諸如:
public class SearchHelper { private object obj = new object(); private static SearchHelper search; private SearchHelper(){} public static SearchHelper Instance { get { if (search == null) { lock (obj) { if (search == null) search = new SearchHelper(); } } return search; } } public string GetSearch() { return "Path"; } }
這種設計初初一看,就不是很順眼。
這種業務類和單例本身強結合的模式,實際應用中,還真帶來了一些麻煩,比如這個SearchHelper, 我有時候需要對某些方法擷取更新某實體後的值,因其單例類模式,直接就無法得到其值,只好繞彎路。
於是重構這個模組,已經是擺在面前。 當然也可以不去重構,讓代碼繼續亂下去,亂下去,亂下去,直到死亡 :-)
經過一番考慮,首先想到的是將這些業務類和單例這個模式強結合的模式分離, 分離後讓單例不再強姦這些業務類。
於是,就有了下文:
第一步:將這些業務類的單例去除,出除後,代碼結構如下:
public class SearchHelper { private SearchHelper(){} public string GetPath() { return "Path"; } }
同理,去除其他所有的業務類的單例。
PathHelper:
public class PathHelper{ private PathHelper(){} public string GetPath() { return "Path"; }
}
MapHelper:
public class MapHelper {
private MapHelper(){} public string GetMap() { return "Map"; } }
第二步:定義個單例專用類,定義一個泛型類,並利用反射特性使其能夠動態按需建立單例
public class Singleton<T> where T : class { static Mutex mutex = new Mutex(); static T instance; private Singleton() { } public static T UniqueInstance { get { mutex.WaitOne(); // enter protected area if (instance == null) { try { instance = SingletonCreator.instance; } catch (Exception ex) { throw ex; } } mutex.ReleaseMutex(); // exit protected area return instance; } } class SingletonCreator { static SingletonCreator() { } // Private object instantiated with private constructor internal static readonly T instance = CreateNewInstance(); private static T CreateNewInstance() { //Get the current assembly object Assembly assembly = Assembly.GetExecutingAssembly(); // Retrieve assembly types Type[] types = assembly.GetTypes(); foreach (Type typeName in types) { Module typeMod = assembly.GetModule(typeName.ToString()); if (typeof(T).IsAssignableFrom(typeName) && (typeName.IsClass)) { // Create and return an instance of the appropriate model object return Activator.CreateInstance(typeName) as T; } } throw new Exception("New instance not found!"); } } }
第三步: 定義一個Dispatcher類,用以得到泛型類的單例。
1 public class Dispatcher2 {3 public static T BuildObject<T>() where T : class4 {5 return Singleton<T>.UniqueInstance;6 }7 }
第四步: 定義一個Facades類,用以得到想要的具體的某業務類的單例。
1 public class Facades 2 { 3 private static SearchHelper searchHelper; 4 private static MapHelper mapHelper; 5 private static PathHelper pathHelper; 6 7 public SearchHelper SearchHelper 8 { 9 get { return searchHelper; }10 }11 12 public MapHelper MapHelper13 {14 get { return mapHelper; }15 }16 17 public PathHelper PathHelper18 {19 get { return pathHelper; }20 }21 public Facades()22 {23 searchHelper = Dispatcher.BuildObject<SearchHelper>();24 mapHelper = Dispatcher.BuildObject<MapHelper>();25 pathHelper = Dispatcher.BuildObject<PathHelper>();26 } 27 }
好了,到此為止,已經將單例模式從業務類中完全解耦。
業務類就是業務來,單例就是單例,無需將單例強加在業務類上。重構後,其檔案結構如下:
重構:將單例模式從業務類中完全解耦