本篇是講設計模式方面的,比較雜,不像書上的那樣。 我們先從很簡單的一個需求開始:“想讓系統中只存在一個SendEmailObject對象” 代碼: public class SendEmailObject { public bool Send() { Console.WriteLine("Email ...
本篇是講設計模式方面的,比較雜,不像書上的那樣。
我們先從很簡單的一個需求開始:“想讓系統中只存在一個SendEmailObject對象”
代碼:
public class SendEmailObject { public bool Send() { Console.WriteLine("Email sent from : "+this.GetHashCode()); //加這個GetHashCode調用是用來查看instance是否同一個的 return false; } } public static class Factory { private static SendEmailObject sendEmail; public static SendEmailObject GetSendEmailObject() { if (sendEmail == null) { lock (typeof(SendEmailObject)) //加了個鎖 { if (sendEmail == null) sendEmail = new SendEmailObject(); } } return sendEmail; } }
main函數中調用代碼:
var o = Factory.GetSendEmailObject(); o.Send(); o = Factory.GetSendEmailObject(); o.Send(); Console.Read();
運行後:
上面的代碼由於和具體的類"SendEmailObject"強耦合了,因此不夠通用,要是我需要有很多個類都需要這樣來控制instance數量的話,就要複製黏貼很多很多code了,所以看下麵的改進:
支持泛型的方法(更通用)
代碼:
public static class Factory { private static Dictionary<Type, object> instances = new Dictionary<Type, object>(); public static T GetInstance<T>() where T : class, new() { T o = null; if (instances.ContainsKey(typeof(T))) o = instances[typeof(T)] as T; if (o == null) { lock (instances) { if (instances.ContainsKey(typeof(T))) o = instances[typeof(T)] as T; if (o == null) { o = new T(); instances[typeof(T)] = o; } } } return o; } public static int GetInstanceCount() //這個方法只是測試用的,真正用的時候要去掉 { return instances.Count; } }
main調用代碼:
var o = Factory.GetInstance<SendEmailObject>(); o.Send(); o = Factory.GetInstance<SendEmailObject>(); o.Send(); o = Factory.GetInstance<SendEmailObject>(); o.Send(); o = Factory.GetInstance<SendEmailObject>(); o.Send(); Console.WriteLine("Factory instance count: " + Factory.GetInstanceCount()); Console.Read();
運行後:
看最後一行輸出,instance數只要一個。哈哈,通用性搞定拉...
上面說的都是要求只要一個instance的情況,要是這個需求呢?“由於SendEmailObject類很重,同時考慮到性能,因此需要做到:方便的訪問+控制instance數量+多個instance同時處理request”,請看下麵的方法:
能控制instance數量(max)的方法,代碼如下:
public static class Factory { private static int MaxInstancePerType = 3; //此處設置了最多3個instance private static Dictionary<Type, List<object>> instances = new Dictionary<Type, List<object>>(); //instance隊列 private static Dictionary<Type, int> instanceCounters = new Dictionary<Type, int>(); //instance相應的計數器隊列 public static T GetInstance<T>() where T : class, new() { lock (instances) //鎖定對象 { if (!instances.ContainsKey(typeof(T))) { List<object> tmplist = new List<object>(); for (int i = 0; i < MaxInstancePerType; i++) { T o = new T(); tmplist.Add(o); } instances.Add(typeof(T), tmplist); instanceCounters.Add(typeof(T), 0); } List<object> list = instances[typeof(T)] as List<object>; int curIndex = instanceCounters[typeof(T)]; T instance = list[curIndex] as T; curIndex++; curIndex = curIndex % MaxInstancePerType; //迴圈取模 instanceCounters[typeof(T)] = curIndex; return instance; } } }
main調用代碼:
SendEmailObject o; for (int i = 0; i < 10; i++) { o = Factory.GetInstance<SendEmailObject>(); o.Send(); } Console.Read();
運行如下:
哈哈,上面的輸出是迴圈的,3個一組的迴圈
下麵我們來點題外話,有人說:“這個object怎麼沒有介面?” ,那好,那就加一個吧,如下:
public interface IEmailService //新增加的介面 { bool Send(); } public class SendEmailObject : IEmailService { public bool Send() { Console.WriteLine("Email sent from : "+this.GetHashCode()); return false; } }
有人說,我想實現這個需求:“我提供一個interface, 工廠返回一個instance”,ok,沒問題,寫寫吧,代碼:
public static class Factory { private static Dictionary<Type, Type> typeMappers = new Dictionary<Type, Type>(); public static void Register<M, N>() where N : class, new() { if (typeMappers.ContainsKey(typeof(M))) throw new Exception("Key existed"); typeMappers.Add(typeof(M), typeof(N)); } public static M Resolve<M>() { if (!typeMappers.ContainsKey(typeof(M))) throw new Exception("Key empty, register please"); Type type = typeMappers[typeof(M)]; return (M)Activator.CreateInstance(type); } }
main調用代碼:
Factory.Register<IEmailService, SendEmailObject>();
IEmailService srv = Factory.Resolve<IEmailService>(); srv.Send();
srv = Factory.Resolve<IEmailService>(); srv.Send();
Console.Read();
運行輸出:
看看,哦,不對啊,這是2個instance啊?! 哈哈,對的,是2個instance,因為上面的代碼里沒有控制instance的數量,有興趣的兄弟改改發不發佈吧,哈哈。
哦,對了,上面的代碼是不是很想Unity的Resolve和StructureMap的Resolve方法?哈哈。