研究简单工厂模式时的一些性能问题
这两天在研究设计模式,现在看来还不知道各种设计模式会具体用在哪些场景中,哈哈,可能还没有达到那种境界吧。
最常用的莫过于工厂模式了。
来个最简单的工厂:
interface IFruit { } class Apple:IFruit { } class Orange:IFruit { } class Factory { public static IFruit Create(string name) { switch (name.ToLower()) { case "apple": return new Apple(); case "orange": return new Orange(); default: return null; } } }
虽然看起来比较明了,但是使用起来的时候,如果你来了一样新的水果,那岂不是还得对工厂方法进行修改,来了多少个,就得增加多少个case,多麻烦。
于是就诞生了使用反射来创建产品的方法。具体如下:
其他类相同,只是修改了工厂方法
namespace 利用反射实现简单工厂 { class Factory { public static IFruit MakeFruit(string name) { try { Type type = Type.GetType("利用反射实现简单工厂."+name,true); IFruit fruit =Activator.CreateInstance(type) as IFruit; return fruit; } catch (Exception e) { Console.WriteLine(e.Message); return null; } } } }
这样,不就一劳永逸了嘛,不管你增加再多的产品,我这工厂通通收了,还不需要进行改造,哈哈~~
那就是先运行试试吧:
使用反射后,性能也相差太大了吧,这可不是在一个数量级的呀,怎么办?
怎么办呀!!!
当然是使用缓存办呀,嘎嘎~~~由于类的实例都是引用类型,自然得使用深拷贝来完成了
private const string spaceName = "研究反射与缓存_深拷贝_的性能.";
private static MemoryCache memoryCache=new MemoryCache("cache");
public static IFruit Make(string name)
{
if(memoryCache.Contains(name))
{
// return memoryCache[name] as IFruit;
return Clone(memoryCache[name]);
}
Type type = Type.GetType(spaceName + name);
IFruit fruit= Activator.CreateInstance(type) as IFruit;
memoryCache.Add(name, fruit, DateTimeOffset.MaxValue);
return fruit;
}
private static IFruit Clone(Object t)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter=new BinaryFormatter();
formatter.Serialize(stream,t);
stream.Position = 0;
return formatter.Deserialize(stream) as IFruit;
}
}
将工厂方法改造下 ,加个缓存,同时使用BinaryFormatter来完成深拷贝,当然别忘了引入一下两个命名空间:
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Caching;
这下总可以了吧,我得意的笑呀
是骡子是马,来出来溜溜
这是不是笑的也太早了点,菇凉~~使用了缓存反倒时间级别又上了一个层次,也太恐怖了吧。~~~~(>_<)~~~~
其实仔细思考下,由于使用了BinaryFormatter 来完成深拷贝,而BinaryFormatter 在反序列化的时候是非常耗时的操作,具体原因大家可以参考园子里一位园友的文章:.net BinaryFormatter序列化对象慢的原因
改吧改吧不是罪,于是又使用了另外的一种深拷贝方法:实现ICloneable接口
public interface IFruit:ICloneable
{
string Name { get; set; }
}
class Apple:IFruit
{
public string Name { get; set; }
public Object Clone()
{
Apple apple=new Apple();
apple.Name = this.Name;
return apple;
}
}
工厂方法也稍微进行了一下修改:
private const string spaceName = "研究反射与缓存_深拷贝_的性能."; public static Dictionary<string,IFruit> dictionary=new Dictionary<string, IFruit>(); public static IFruit Make(string name) { if(dictionary.ContainsKey(name)) { IFruit friFruit; dictionary.TryGetValue(name, out friFruit); return friFruit.Clone() as IFruit; } Type type = Type.GetType(spaceName + name); IFruit fruit = Activator.CreateInstance(type) as IFruit; dictionary.Add(name,fruit); return fruit; }
最后再来运行试试:
哈哈,这下是不是很爽,看着这时间级别~
以上就是个人对简单工厂性能方面的一些理解 ,可能存在不正确的地方,还望各位指正。
源代码下载:研究反射与缓存(深拷贝)的性能.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库