這兩天在研究設計模式,現在看來還不知道各種設計模式會具體用在哪些場景中,哈哈,可能還沒有達到那種境界吧。
最常用的莫過於工廠模式了。
來個最簡單的工廠:
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