翼度科技»论坛 编程开发 .net 查看内容

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

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
概述

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

我们先来看一看这样一个案例,小学生玩的四则运算,当客户输入两个数,然后输入一个操作符,获得结果!我们先用简单工厂写下逻辑代码,验证下简单工厂的缺点。
简单工厂代码
  1.    /// <summary>
  2.     ///  静态工作方法 实际上就是把创建对象的过程放到静态方法里面
  3.     /// </summary>
  4.     public class CalFactory
  5.     {
  6.         public static ICalculator GetCalculator(string oper)
  7.         {
  8.             ICalculator? calculator = null;
  9.             switch (oper)
  10.             {
  11.                 case "*":
  12.                     calculator = new Mul();
  13.                     break;
  14.                 case "+":
  15.                     calculator = new Add();
  16.                     break;
  17.                 case "-":
  18.                     calculator = new Sub();
  19.                     break;
  20.                 case "/":
  21.                     calculator = new Div();
  22.                     break;
  23.             }
  24.             return calculator;
  25.         }
  26.     }
复制代码
  1.    public interface  ICalculator
  2.     {
  3.         double GetResult(double d1,double d2);
  4.     }
  5.     public class Add : ICalculator
  6.     {
  7.         public double GetResult(double d1, double d2)
  8.         {
  9.            return d1+ d2;   
  10.         }
  11.     }
  12.     public class Sub : ICalculator
  13.     {
  14.         public double GetResult(double d1, double d2)
  15.         {
  16.             return d1-d2;
  17.         }
  18.     }
  19.     public class Mul : ICalculator
  20.     {
  21.         public double GetResult(double d1, double d2)
  22.         {
  23.             return d1* d2;
  24.         }
  25.     }
  26.     public class Div : ICalculator
  27.     {
  28.         public double GetResult(double d1, double d2)
  29.         {
  30.             return d1 / d2;
  31.         }
复制代码
  1. //C# 控制台调用
  2. Console.WriteLine("简单工厂设计模式!");
  3. Console.WriteLine("请输入操作数1");
  4. var d1 = Convert.ToDouble(Console.ReadLine());
  5. Console.WriteLine("请输入操作数2");
  6. var d2 = Convert.ToDouble(Console.ReadLine());
  7. ICalculator calculator = null;
  8. Console.WriteLine("请输入操作符");
  9. string flag=Console.ReadLine();
  10. calculator= CalFactory.GetCalculator(flag);   
  11. double reslut= calculator.GetResult(d1,d2);
  12. Console.WriteLine(reslut);
复制代码
这个需求的代码逻辑很简单,一看基本就会,我们主要说下简单工厂模式的优缺点;
优点:
1、简单工厂设计模式解决了客户端直接依赖具体对象的问题,客户端消除了创建对象的责任,仅仅承担使用的责任。简单工厂模式实现了对责任的分割;
2、简单工厂起到了代码复用的作用;
缺点:
1、系统扩展困难,一旦加入新功能,就必须要修改工厂逻辑。破坏了开闭原则;
2、简单工厂集合了多有创建对象的逻辑,一旦不能正常工作,会导致整个系统出问题;
工厂方法代码

还是上面的需求,我们定义一个创建对象的接口,让子类决定实例化哪一个类。
  1.     public interface ICalFactory
  2.     {
  3.         ICalculator GetCalculator();
  4.     }
  5.     public class MulFactory : ICalFactory
  6.     {
  7.         public ICalculator GetCalculator()
  8.         {
  9.             return new Mul();
  10.         }
  11.     }
  12.   public class AddFactory : ICalFactory
  13.     {
  14.         public ICalculator GetCalculator()
  15.         {
  16.             return new Add();
  17.         }
  18.     }
  19.   public class SubFactory : ICalFactory
  20.     {
  21.         public ICalculator GetCalculator()
  22.         {
  23.             return new Sub();
  24.         }
  25.     }
  26.     public class DivFactory : ICalFactory
  27.     {
  28.         public ICalculator GetCalculator()
  29.         {
  30.             return new Div();
  31.         }
  32.     }
复制代码
  1.    public interface ICalculator
  2.     {
  3.         double GetResult(double d1, double d2);
  4.     }
  5.     public class Add : ICalculator
  6.     {
  7.         public double GetResult(double d1, double d2)
  8.         {
  9.             return d1 + d2;
  10.         }
  11.     }
  12.     public class Sub : ICalculator
  13.     {
  14.         public double GetResult(double d1, double d2)
  15.         {
  16.             return d1 - d2;
  17.         }
  18.     }
  19.     public class Mul : ICalculator
  20.     {
  21.         public double GetResult(double d1, double d2)
  22.         {
  23.             return d1 * d2;
  24.         }
  25.     }
  26.     public class Div : ICalculator
  27.     {
  28.         public double GetResult(double d1, double d2)
  29.         {
  30.             return d1 / d2;
  31.         }
  32.     }
复制代码
  1. //C# 控制台调用
  2. Console.WriteLine("请输入操作数1");
  3. var d1 = Convert.ToDouble(Console.ReadLine());
  4. Console.WriteLine("请输入操作数2");
  5. var d2 = Convert.ToDouble(Console.ReadLine());
  6. Console.WriteLine("请输入操作符");
  7. string flag = Console.ReadLine();
  8. ICalFactory? calFactory = null;
  9. switch (flag)
  10. {
  11.     case "*":
  12.         calFactory = new MulFactory();
  13.         break;
  14.     case "+":
  15.         calFactory = new AddFactory();
  16.         break;
  17.     case "-":
  18.         calFactory = new SubFactory();
  19.         break;
  20.     case "/":
  21.         calFactory = new DivFactory();
  22.         break;
  23. }
  24. ICalculator calculator=calFactory?.GetCalculator();
  25. var result= calculator.GetResult(d1, d2);
  26. Console.WriteLine(result);
复制代码
我们目前是使用了工厂方法设计模式来实现了需求,但能看到源码里面有一坨switch case,我们接下来通过反射处理switch case
没有switch case的工厂方法代码
  1. public class OperFactory:Attribute
  2.     {
  3.         public string  Oper { get;  }
  4.         public OperFactory(string value)
  5.         {
  6.             Oper=value;
  7.         }
  8.     }
复制代码
  1.   public class ReflectionFactory
  2.     {
  3.         //根据用户输入的操作符 返回一个对象
  4.         Dictionary<string, ICalFactory> dic=new Dictionary<string, ICalFactory>();
  5.         public ReflectionFactory()
  6.         {
  7.             //拿到当前正在运行的程序集
  8.             Assembly assembly= Assembly.GetExecutingAssembly();
  9.             foreach (var item in assembly.GetTypes())
  10.             {
  11.                 //IsAssignableFrom 表示item继承了ICalFactory或实现了ICalFactory
  12.                 if (typeof(ICalFactory).IsAssignableFrom(item)&&!item.IsInterface)
  13.                 {
  14.                     OperFactory of= item.GetCustomAttribute<OperFactory>();
  15.                     if (of != null)
  16.                     {
  17.                         //给键值对集合赋值
  18.                         dic[of.Oper] = Activator.CreateInstance(item) as ICalFactory;
  19.                     }
  20.                 }
  21.             }
  22.         }
  23.         public ICalFactory GetFac(string s)
  24.         {
  25.             if (dic.ContainsKey(s))
  26.             {
  27.                 return dic[s];
  28.             }
  29.             return null;
  30.         }
  31.     }
复制代码
  1.    public interface ICalFactory
  2.     {
  3.         ICalculator GetCalculator();
  4.     }
  5.     [OperFactory("*")]
  6.     public class MulFactory : ICalFactory
  7.     {
  8.         public ICalculator GetCalculator()
  9.         {
  10.             return new Mul();
  11.         }
  12.     }
  13.     [OperFactory("+")]
  14.     public class AddFactory : ICalFactory
  15.     {
  16.         public ICalculator GetCalculator()
  17.         {
  18.             return new Add();
  19.         }
  20.     }
  21.     [OperFactory("-")]
  22.     public class SubFactory : ICalFactory
  23.     {
  24.         public ICalculator GetCalculator()
  25.         {
  26.             return new Sub();
  27.         }
  28.     }
  29.     [OperFactory("/")]
  30.     public class DivFactory : ICalFactory
  31.     {
  32.         public ICalculator GetCalculator()
  33.         {
  34.             return new Div();
  35.         }
  36.     }
复制代码
  1. //C# 控制台调用
  2. ReflectionFactory reflectionFactory = new ReflectionFactory();
  3. ICalFactory calFactory2=  reflectionFactory.GetFac(flag);
  4. var result2= calFactory2.GetCalculator().GetResult(d1, d2);
  5. Console.WriteLine(result2);
复制代码
总结

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

来源:https://www.cnblogs.com/mhg215/archive/2023/02/15/17119131.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具