研究简单工厂模式时的一些性能问题
这两天在研究设计模式,现在看来还不知道各种设计模式会具体用在哪些场景中,哈哈,可能还没有达到那种境界吧。
最常用的莫过于工厂模式了。
来个最简单的工厂:
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