研究簡單工廠模式時的一些性能問題


   這兩天在研究設計模式,現在看來還不知道各種設計模式會具體用在哪些場景中,哈哈,可能還沒有達到那種境界吧。

   最常用的莫過於工廠模式了。

   來個最簡單的工廠:

  

    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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM