经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
写给准备跳槽的小伙伴们的设计模式——工厂方法设计模式
来源:cnblogs  作者:realyrare  时间:2023/2/15 9:21:16  对本文有异议

概述

工厂方法模式(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/p/17119131.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号