柴大气粗 发表于 2023-2-15 08:57:11

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

概述

工厂方法模式(FactoryMethod),定义一个创建产品对象的工厂接口,让工厂子类决定实例化那一个产品类。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”(可以通过反射克服该缺点)。
工厂方法模式是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
 
需求案例

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

   /// <summary>
    ///静态工作方法 实际上就是把创建对象的过程放到静态方法里面
    /// </summary>
    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 interfaceICalculator
    {
      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 stringOper { 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<OperFactory>();
                  if (of != null)
                  {
                        //给键值对集合赋值
                        dic = Activator.CreateInstance(item) as ICalFactory;
                  }
                }
            }
      }

      public ICalFactory GetFac(string s)
      {
            if (dic.ContainsKey(s))
            {
                return dic;
            }
            return null;
      }
    }   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();
      }
    }//C# 控制台调用
ReflectionFactory reflectionFactory = new ReflectionFactory();
ICalFactory calFactory2=reflectionFactory.GetFac(flag);
var result2= calFactory2.GetCalculator().GetResult(d1, d2);
Console.WriteLine(result2);总结

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

来源:https://www.cnblogs.com/mhg215/archive/2023/02/15/17119131.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 写给准备跳槽的小伙伴们的设计模式——工厂方法设计模式