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

  • 写给准备跳槽的小伙伴们的设计模式——工厂方法设计模式已关闭评论
  • 134 次浏览
  • A+
所属分类:.NET技术
摘要

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


概述

工厂方法模式(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 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<OperFactory>();                     if (of != null)                     {                         //给键值对集合赋值                         dic[of.Oper] = Activator.CreateInstance(item) as ICalFactory;                     }                 }             }         }          public ICalFactory GetFac(string s)         {             if (dic.ContainsKey(s))             {                 return dic展开;             }             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);

总结

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