不懂设计模式
本篇是讲设计模式方面的,比较杂,不像书上的那样。
我们先从很简单的一个需求开始:“想让系统中只存在一个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方法?哈哈。
囧:上面的代码是设计模式的哪种,偶是分不清的...哈哈
心怀远大理想。
为了家庭幸福而努力。
商业合作请看此处:https://www.magicube.ai
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2011-04-11 负载均衡之---应用请求路由模块的使用(ARR)(四)[使用ARR实现HTTP负载均衡]