• 写给准备跳槽的小伙伴们的设计模式——工厂方法设计模式


    概述

    工厂方法模式(FactoryMethod),定义一个创建产品对象的工厂接口,让工厂子类决定实例化那一个产品类。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”(可以通过反射克服该缺点)。

    工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。


     

    需求案例

    我们先来看一看这样一个案例,小学生玩的四则运算,当客户输入两个数,然后输入一个操作符,获得结果!我们先用简单工厂写下逻辑代码,验证下简单工厂的缺点。

    简单工厂代码

    复制代码
       /// 
        ///  静态工作方法 实际上就是把创建对象的过程放到静态方法里面
        /// 
        public class CalFactory
        {
            public static ICalculator GetCalculator(string oper)
            {
                ICalculator? calculator = null;
                switch (oper)
                {
                    case "*":
                        calculator = new Mul();
                        break;
                    case "+":
                        calculator = new Add();
                        break;
                    case "-":
                        calculator = new Sub();
                        break;
                    case "/":
                        calculator = new Div();
                        break;
                }
                return calculator;
            }
        }
    复制代码
    复制代码
       public interface  ICalculator
        {
            double GetResult(double d1,double d2);
        }
    
        public class Add : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
               return d1+ d2;   
            }
        }
        public class Sub : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1-d2;
            }
        }
        public class Mul : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1* d2;
            }
        }
        public class Div : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1 / d2;
            }
    复制代码
    复制代码
    //C# 控制台调用
    Console.WriteLine("简单工厂设计模式!");
    Console.WriteLine("请输入操作数1");
    var d1 = Convert.ToDouble(Console.ReadLine());
    Console.WriteLine("请输入操作数2");
    var d2 = Convert.ToDouble(Console.ReadLine());
    ICalculator calculator = null;
    Console.WriteLine("请输入操作符");
    string flag=Console.ReadLine();
    
    calculator= CalFactory.GetCalculator(flag);   
    double reslut= calculator.GetResult(d1,d2);
    Console.WriteLine(reslut);
    复制代码

    这个需求的代码逻辑很简单,一看基本就会,我们主要说下简单工厂模式的优缺点;

    优点:

    1、简单工厂设计模式解决了客户端直接依赖具体对象的问题,客户端消除了创建对象的责任,仅仅承担使用的责任。简单工厂模式实现了对责任的分割;
    2、简单工厂起到了代码复用的作用;
    缺点:
    1、系统扩展困难,一旦加入新功能,就必须要修改工厂逻辑。破坏了开闭原则;
    2、简单工厂集合了多有创建对象的逻辑,一旦不能正常工作,会导致整个系统出问题;

    工厂方法代码

    还是上面的需求,我们定义一个创建对象的接口,让子类决定实例化哪一个类。

    复制代码
        public interface ICalFactory
        {
            ICalculator GetCalculator();
        }
        public class MulFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Mul();
            }
        }
      public class AddFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Add();
            }
        }
      public class SubFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Sub();
            }
        }
        public class DivFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Div();
            }
        }
    复制代码
    复制代码
       public interface ICalculator
        {
            double GetResult(double d1, double d2);
        }
    
        public class Add : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1 + d2;
            }
        }
        public class Sub : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1 - d2;
            }
        }
        public class Mul : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1 * d2;
            }
        }
        public class Div : ICalculator
        {
            public double GetResult(double d1, double d2)
            {
                return d1 / d2;
            }
        }
    复制代码
    复制代码
    //C# 控制台调用
    Console.WriteLine("请输入操作数1");
    var d1 = Convert.ToDouble(Console.ReadLine());
    Console.WriteLine("请输入操作数2");
    var d2 = Convert.ToDouble(Console.ReadLine());
    
    Console.WriteLine("请输入操作符");
    string flag = Console.ReadLine();
    
    ICalFactory? calFactory = null;
    
    switch (flag)
    {
        case "*":
            calFactory = new MulFactory();
            break;
        case "+":
            calFactory = new AddFactory();
            break;
        case "-":
            calFactory = new SubFactory();
            break;
        case "/":
            calFactory = new DivFactory();
            break;
    }
    
    ICalculator calculator=calFactory?.GetCalculator();
    var result= calculator.GetResult(d1, d2);
    Console.WriteLine(result);
    复制代码

    我们目前是使用了工厂方法设计模式来实现了需求,但能看到源码里面有一坨switch case,我们接下来通过反射处理switch case

    没有switch case的工厂方法代码

    复制代码
     public class OperFactory:Attribute
        {
            public string  Oper { get;  }
            public OperFactory(string value)
            {
                Oper=value;
            }
        }
    复制代码
    复制代码
      public class ReflectionFactory
        {
            //根据用户输入的操作符 返回一个对象
            Dictionary<string, ICalFactory> dic=new Dictionary<string, ICalFactory>();
            public ReflectionFactory()
            {
                //拿到当前正在运行的程序集
                Assembly assembly= Assembly.GetExecutingAssembly();
                foreach (var item in assembly.GetTypes())
                {
                    //IsAssignableFrom 表示item继承了ICalFactory或实现了ICalFactory
                    if (typeof(ICalFactory).IsAssignableFrom(item)&&!item.IsInterface)
                    {
                        OperFactory of= item.GetCustomAttribute();
                        if (of != null)
                        {
                            //给键值对集合赋值
                            dic[of.Oper] = Activator.CreateInstance(item) as ICalFactory;
                        }
                    }
                }
            }
    
            public ICalFactory GetFac(string s)
            {
                if (dic.ContainsKey(s))
                {
                    return dic[s];
                }
                return null;
            }
        }
    复制代码
    复制代码
       public interface ICalFactory
        {
            ICalculator GetCalculator();
        }
        [OperFactory("*")]
        public class MulFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Mul();
            }
        }
        [OperFactory("+")]
        public class AddFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Add();
            }
        }
        [OperFactory("-")]
        public class SubFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Sub();
            }
        }
        [OperFactory("/")]
        public class DivFactory : ICalFactory
        {
            public ICalculator GetCalculator()
            {
                return new Div();
            }
        }
    复制代码
    //C# 控制台调用
    ReflectionFactory reflectionFactory = new ReflectionFactory();
    ICalFactory calFactory2=  reflectionFactory.GetFac(flag);
     var result2= calFactory2.GetCalculator().GetResult(d1, d2);
    Console.WriteLine(result2);

    总结

    一个四则运算的需求,分别采用简单工厂和工厂方法实现,其实各有优缺点,使用哪种设计模式主要取决于自己的业务,有何疑问,欢迎交流。

  • 相关阅读:
    便携式手持蒸汽电熨斗UL859测试项目介绍
    【算法题】2909. 元素和最小的山形三元组 II
    如何在 pyqt 中实现桌面歌词
    java培训技术-返回JSON
    RTL8380M管理型交换机系统软件操作指南一:端口配置
    Impedit odio facilis ad.Quinze également passer billet mensonge animer libre.
    java 入门-使用eclipse、javaFX、SceneBuilder进行图形界面开发
    Spring 事务传播行为
    Android 13.0 系统go版添加支持AppWidget小部件功能的实现
    12.optimizer优化器和evaluate评估
  • 原文地址:https://www.cnblogs.com/mhg215/p/17119131.html