码迷,mamicode.com
首页 > 其他好文 > 详细

不懂设计模式

时间:2016-07-07 09:55:18      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

本篇是讲设计模式方面的,比较杂,不像书上的那样。

我们先从很简单的一个需求开始:“想让系统中只存在一个SendEmailObject对象”

代码:

技术分享
public class SendEmailObject
    {
        public bool Send()
        {
            Console.WriteLine("Email sent from : "+this.GetHashCode());       //加这个GetHashCode调用是用来查看instance是否同一个的
            return false;
        }
    }

    public static class Factory
    {
        private static SendEmailObject sendEmail;
        public static SendEmailObject GetSendEmailObject()
        {
            if (sendEmail == null)
            {
                lock (typeof(SendEmailObject))              //加了个锁
                {
                    if (sendEmail == null)
                        sendEmail = new SendEmailObject();
                }
            }
            return sendEmail;
        }
    }
技术分享

 main函数中调用代码:

            var o = Factory.GetSendEmailObject();
            o.Send();
            o = Factory.GetSendEmailObject();
            o.Send();
            Console.Read();

 运行后:
技术分享

 上面的代码由于和具体的类"SendEmailObject"强耦合了,因此不够通用,要是我需要有很多个类都需要这样来控制instance数量的话,就要复制黏贴很多很多code了,所以看下面的改进:

支持泛型的方法(更通用)

代码:

技术分享
public static class Factory
    {
        private static Dictionary<Type, object> instances = new Dictionary<Type, object>();
        public static T GetInstance<T>()
            where T : class, new()
        {
            T o = null;
            if (instances.ContainsKey(typeof(T)))
                o = instances[typeof(T)] as T;
            if (o == null)
            {
                lock (instances)
                {
                    if (instances.ContainsKey(typeof(T)))
                        o = instances[typeof(T)] as T;
                    if (o == null)
                    {
                        o = new T();
                        instances[typeof(T)] = o;
                    }
                }
            }
            return o;
        }

        public static int GetInstanceCount()        //这个方法只是测试用的,真正用的时候要去掉
        {
            return instances.Count;
        }
    }
技术分享

 

 main调用代码:

技术分享
            var o = Factory.GetInstance<SendEmailObject>();
            o.Send();
            o = Factory.GetInstance<SendEmailObject>();
            o.Send();
            o = Factory.GetInstance<SendEmailObject>();
            o.Send();
            o = Factory.GetInstance<SendEmailObject>();
            o.Send();
            Console.WriteLine("Factory instance count: " + Factory.GetInstanceCount());
            Console.Read();
技术分享

 

运行后:
技术分享

看最后一行输出,instance数只要一个。哈哈,通用性搞定拉...

 

上面说的都是要求只要一个instance的情况,要是这个需求呢?“由于SendEmailObject类很重,同时考虑到性能,因此需要做到:方便的访问+控制instance数量+多个instance同时处理request”,请看下面的方法:

能控制instance数量(max)的方法,代码如下:

技术分享
public static class Factory
    {
        private static int MaxInstancePerType = 3;  //此处设置了最多3个instance
        private static Dictionary<Type, List<object>> instances = new Dictionary<Type, List<object>>();     //instance队列
        private static Dictionary<Type, int> instanceCounters = new Dictionary<Type, int>();                //instance相应的计数器队列
        public static T GetInstance<T>()
            where T : class, new()
        {
            lock (instances)    //锁定对象
            {
                if (!instances.ContainsKey(typeof(T)))
                {
                    List<object> tmplist = new List<object>();

                    for (int i = 0; i < MaxInstancePerType; i++)
                    {
                        T o = new T();
                        tmplist.Add(o);
                    }

                    instances.Add(typeof(T), tmplist);
                    instanceCounters.Add(typeof(T), 0);
                }
                List<object> list = instances[typeof(T)] as List<object>;
                int curIndex = instanceCounters[typeof(T)];

                T instance = list[curIndex] as T;
                curIndex++;
                curIndex = curIndex % MaxInstancePerType;   //循环取模
                instanceCounters[typeof(T)] = curIndex;
                return instance;
            }
        }
    }
技术分享

 

main调用代码:

技术分享
            SendEmailObject o;
            for (int i = 0; i < 10; i++)
            {
                o = Factory.GetInstance<SendEmailObject>();
                o.Send();
            }
            Console.Read();
技术分享

 

运行如下:
技术分享

哈哈,上面的输出是循环的,3个一组的循环

 

下面我们来点题外话,有人说:“这个object怎么没有接口?” ,那好,那就加一个吧,如下:

技术分享
 public interface IEmailService        //新增加的接口
    {
        bool Send();
    }

    public class SendEmailObject : IEmailService
    {
        public bool Send()
        {
            Console.WriteLine("Email sent from : "+this.GetHashCode());
            return false;
        }
    }
技术分享

 

有人说,我想实现这个需求:“我提供一个interface, 工厂返回一个instance”,ok,没问题,写写吧,代码:

技术分享
public static class Factory
    {
        private static Dictionary<Type, Type> typeMappers = new Dictionary<Type, Type>();
        public static void Register<M, N>()
            where N : class, new()
        {
            if (typeMappers.ContainsKey(typeof(M)))
                throw new Exception("Key existed");

            typeMappers.Add(typeof(M), typeof(N));
        }

        public static M Resolve<M>()
        {
            if (!typeMappers.ContainsKey(typeof(M)))
                throw new Exception("Key empty, register please");
            Type type = typeMappers[typeof(M)];
            return (M)Activator.CreateInstance(type);
        }
    }
技术分享

 

main调用代码:

技术分享
Factory.Register<IEmailService, SendEmailObject>();
IEmailService srv
= Factory.Resolve<IEmailService>(); srv.Send();
srv = Factory.Resolve<IEmailService>();
srv.Send();
Console.Read();
技术分享

 

运行输出:
技术分享

看看,哦,不对啊,这是2个instance啊?! 哈哈,对的,是2个instance,因为上面的代码里没有控制instance的数量,有兴趣的兄弟改改发不发布吧,哈哈。

哦,对了,上面的代码是不是很想Unity的Resolve和StructureMap的Resolve方法?哈哈。

 

不懂设计模式

标签:

原文地址:http://www.cnblogs.com/androidshouce/p/5648842.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!