本篇是讲设计模式方面的,比较杂,不像书上的那样。
我们先从很简单的一个需求开始:“想让系统中只存在一个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方法?哈哈。
时间: 2024-10-20 02:27:57