什么是简单工厂模式?

简单工厂模式(Simple Factory),解决的是在多个基类的继承类中如何选择对应的类实例化。

到底要实例化哪一个继承类?——这就是简单工厂模式整天思考的问题。而之所以会出现这个问题是由于软件架构时接口隔离原则所导致的。接口隔离原则让整个软件架构松耦合,也带来了一些问题,但是跟它的好处相比实在是不值一提,并且这些问题使用工厂模式能够很好的解决。

工厂模式细分之下有三种:简单工厂、工厂方法、抽象工厂。其中,简单工厂模式是理解其他两种模式的基础,一起来看看。

实现简易计算器

光说不练假把式,看起来还头疼。我们以一个简易计算器的实现来一窥该模式的奥妙。计算器的要求如下:
“实现一个计算器程序,要求输入两个数和运算符号,得到结果,暂时实现加减乘除即可,考虑之后的运算符扩充。”

简单工厂模式下的UML类图为:
image.png
操作运算类
为了方便后期复用,将操作运算符实现为一个基类,送入两个参数并通过公共方法返回结果。

  1. package com.whitedew.SimpleFactory;
  2. //操作类
  3. public class Operation {
  4. //子类能继承父类的所有属性,但父类若为私有属性,子类只是拥有,无法使用。
  5. //因此使用protected修饰
  6. protected double numberA = 0;
  7. protected double numberB = 0;
  8. public double getNumberA() {
  9. return numberA;
  10. }
  11. public void setNumberA(double numberA) {
  12. this.numberA = numberA;
  13. }
  14. public double getNumberB() {
  15. return numberB;
  16. }
  17. public void setNumberB(double numberB) {
  18. this.numberB = numberB;
  19. }
  20. public double getResult() {
  21. double result = 0;
  22. return result;
  23. }
  24. }

加减乘除运算
实现加法:

  1. package com.whitedew.SimpleFactory;
  2. public class OperationAdd extends Operation {
  3. @Override
  4. public double getResult() {
  5. double result = 0;
  6. result = numberA + numberB;
  7. return result;
  8. }
  9. }

实现乘法:

  1. package com.whitedew.SimpleFactory;
  2. public class OperationMulti extends Operation {
  3. @Override
  4. public double getResult() {
  5. double result = 0;
  6. result = numberA * numberB;
  7. return result;
  8. }
  9. }

减法除法等见项目代码,
简单工厂代码
简单工厂代码如下,简单来说,就是使用静态方法,通过接收的参数的不同来返回不同的对象实例

  1. package com.whitedew.SimpleFactory;
  2. //运算符工厂的简单工厂模式
  3. //使用静态方法,通过接收的参数的不同来返回不同的对象实例。
  4. public class OperationFactory {
  5. public static Operation createOperate(String operate) {
  6. Operation operation = null;
  7. if (operate == null) {
  8. System.out.println("操作符为空");
  9. System.exit(0);
  10. }
  11. switch (operate) {
  12. case "+":
  13. operation = new OperationAdd();
  14. break;
  15. case "-":
  16. operation = new OperationSub();
  17. break;
  18. case "*":
  19. operation = new OperationMulti();
  20. break;
  21. case "/":
  22. operation = new OperationDiv();
  23. break;
  24. default:
  25. System.out.println("操作符为空");
  26. System.exit(0);
  27. }
  28. return operation;
  29. }
  30. }

计算器客户端
写一个控制台程序试试:

  1. package com.whitedew.SimpleFactory;
  2. import java.util.Scanner;
  3. //计算器运算符
  4. public class CalculatorClient {
  5. public static void main(String[] args) {
  6. int numberA = 0;
  7. int numberB = 0;
  8. String operationStr = null;
  9. Scanner scanner = new Scanner(System.in);
  10. System.out.print("请输入数字A : ");
  11. // 判断是否还有输入
  12. if (scanner.hasNext()) {
  13. numberA = scanner.nextInt();
  14. System.out.println("输入的数据为:" + numberA);
  15. }
  16. System.out.print("请选择运算符(+-*/): ");
  17. // 判断是否还有输入
  18. if (scanner.hasNext()) {
  19. operationStr = scanner.next();
  20. System.out.println("选择的运算符为:" + operationStr);
  21. }
  22. System.out.print("请输入数字B : ");
  23. // 判断是否还有输入
  24. if (scanner.hasNext()) {
  25. numberB = scanner.nextInt();
  26. System.out.println("输入的数据为:" + numberB);
  27. }
  28. Operation operation;
  29. operation = OperationFactory.createOperate(operationStr);
  30. operation.setNumberA(numberA);
  31. operation.setNumberB(numberB);
  32. double result = operation.getResult();
  33. System.out.println("结果为" + numberA + operationStr + numberB + "=" + result);
  34. }
  35. }

结果如下:
image.png

总结

从上面的例子可以看出,简单工厂模式的作用就是根据输入参数来确定到底返回哪一个子类的实例
为什么称为简单工厂模式?仅用一个单独的类来做创造实例的过程,这个类就是工厂。而简单二字是为了与后面的工厂方法、抽象工厂相区分,见后续的4-5章节。
它的优点很明显,降低了系统的耦合度。扩展性强,后期增加一个新的运算符只需要扩展一个对应的子类即可。

参考资料

《大话设计模式》