研究简单工厂模式时的一些性能问题

   这两天在研究设计模式,现在看来还不知道各种设计模式会具体用在哪些场景中,哈哈,可能还没有达到那种境界吧。

   最常用的莫过于工厂模式了。

   来个最简单的工厂:

  

    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

 

posted @ 2012-06-07 10:02 cuitsl 阅读(...) 评论(...) 编辑 收藏
友情博客:大熊的外星球