這兩天在研究設計模式,現在看來還不知道各種設計模式會具體用在哪些情境中,哈哈,可能還沒有達到那種境界吧。
最常用的莫過於原廠模式了。
來個最簡單的工廠:
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; } } }
雖然看起來比較明了,但是使用起來的時候,如果你來了一樣新的水果,那豈不是還得對Factory 方法進行修改,來了多少個,就得增加多少個case,多麻煩。
於是就誕生了使用反射來建立產品的方法。具體如下:
其他類相同,只是修改了Factory 方法
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; } }
將Factory 方法改造下 ,加個緩衝,同時使用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; } }
Factory 方法也稍微進行了一下修改:
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