跟着项目学设计模式(五):简单工厂+单例模式+静态类+延迟加载

版权声明:本文为博主原创文章,未经博主允许不得转载。博客地址: https://blog.csdn.net/m0_37057454/article/details/82025399

接上文,项目交付之后,我们的类库开发人员发现自己穿越了,回到【设计模式——2、简单工厂模式】这篇文章所在时间线的最末尾。

由于穿越所造成的蝴蝶效应,这个项目后期虽然确实需要扩展,但是只是要增加五到六个产品类,并要求尽快交付,以便将关注点放到其他更有价值的项目中去,那赶快来扩充我们的简单工厂吧。

    public class Factory
    {
        /// <summary>
        /// 静态方法创建Product实例
        /// </summary>
        public static IProduct CreateProduct(string name)
        {
            switch(name)
            {
                case "USER":return new UserDal();break;
                case "GOODS":return new GoodsDal();break;
                case "HISTORY":return new HistoryDal();break;
                ...
            }
        }
    }

 代码很快写完了,测试通过,但是下一步sonar代码质量检测,在工厂类的CreateProduct方法里却发现两个问题,

第一是return和break那里有坏味道,也是,都已经return了,还怎么break?(好吧,是我强行这么写只是为了推荐一下sonar),那就改成switch里用变量赋值,最后再return那个变量吧。

第二是方法圈复杂度刚好超过10了,这个扎心了,没法解决,重构吧!

基本思路:用字典代替switch分支

    //工厂类
    public class Factory
    {
        public static readonly Dictionary<string, IProduct> dictionary = new Dictionary<string, IProduct>()
        {
            { "USER", new UserDal() },
            { "GOODS", new GoodsDal() },
            { "HISTORY", new HistoryDal() },
            ...
        };
        /// <summary>
        /// 静态方法创建Product实例
        /// </summary>
        public static IProduct CreateProduct(string name)
        {
            return dictionary[name];
        }
    }

现在圈复杂度的问题彻底解决了,我们通过静态常量dictionary和静态方法CreateProduct实现的,唯一的缺点是在第一次调用Factory的时候,会把所有对象创建一次,要知道这可是单层架构,所有的初始化工作都在里面了,性能何在?加入Lazy<T>延迟加载后能很好地解决这个问题!

    //工厂类
    public class Factory
    {
        public static readonly Dictionary<string, Lazy<IProduct>> dictionary = new Dictionary<string, Lazy<IProduct>>()
        {
            { "USER", new Lazy<IProduct>(() => new UserDal(), true) },
            { "GOODS", new Lazy<IProduct>(() => new GoodsDal(), true) },
            { "HISTORY", new Lazy<IProduct>(() => new HistoryDal(), true) },
            ...
        };
        /// <summary>
        /// 静态方法创建Product实例
        /// </summary>
        public static IProduct CreateProduct(string name)
        {
            return dictionary[name].Value;
        }
    }

现在产品对象只会在第一次调用的时候创建,而不是调用Factory的时候全部创建。

继续来看,项目组觉得这个方案很有价值,要求以后用到简单工厂的项目都这样干。做法就是所有的简单工厂类必须去实现ISampleFactory这个接口。

    public interface ISampleFactory
    {
        Dictionary<string, Lazy<IProduct>> Products { get; set; }
        IProduct CreateProduct(string name);
    }

前面通过静态常量和静态方法做的工作,随着接口的出现,全部作废了。因为静态和接口是宿敌了,一个是面向过程的方法集合,一个是面向对象的高阶面向接口。接口里定义的属性和方法只有对象才能调用,而静态类压根就没有对象。

实现接口的类不能是静态的,类所实现的属性和方法也不能是静态的,所以静态用不了,而且Products也从常量变成了属性。

扫描二维码关注公众号,回复: 2925977 查看本文章

静态被否定了,也只能用单例模式了。我们可以把Dictionary<string, Lazy<IProduct>> Products这个字段的初始化放到私有构造函数里,而单例模式只有一个实例,不就意味着Products只会被初始化1次喽。

    //工厂类
    public class Factory : ISampleFactory
    {
        private static Factory instance;//静态实例

        private Factory()
        {
            Products = new Dictionary<string, Lazy<IProduct>>
            {
               { "USER", new Lazy<IProduct>(() => new UserDal(), true) },
               { "GOODS", new Lazy<IProduct>(() => new GoodsDal(), true) },
               { "HISTORY", new Lazy<IProduct>(() => new HistoryDal(), true) },
               ...
            };
        }

        public static Factory GetInstance()//方法,方法中去实例化类.
        {
            if (instance == null)
            {
                instance = new Factory();
            }
            return instance;
        }

        public Dictionary<string, Lazy<IProduct>> Products { get; set; }

        IProduct ISampleFactory.CreateProduct(string name)
        {
            return Products[name].Value;
        }
    }

好了,运用单例模式完美的解决了接口与静态的矛盾,单例模式真的是非常给力的设计模式。

待续。。。

猜你喜欢

转载自blog.csdn.net/m0_37057454/article/details/82025399
今日推荐