设计模式-简单工厂模式

时间 2019/3/24 11:27:23 加载中...

场景

老大:

做个简单的加减乘除功能

我:

好的,那我先用java做个控制台版本的。

老大:

可以

于是,我开始动工,使用 eclipse 新建了一个简单的控制台项目,写下如下的代码:

  1. import java.util.Scanner;
  2. public class SimplePattern {
  3. public static void main(String[] args) {
  4. Scanner scanner = new Scanner(System.in);
  5. System.out.println("目前支持 加、减、乘、除 四种运算 \r加法请输入1,减法请输入2,乘法请输入3,除法请输入4。");
  6. System.out.println("请选择算法:");
  7. String operateNum = scanner.nextLine();
  8. //对 operateNum 的验证略(非空验证,值为1,2,3,4其中一个值的验证)
  9. System.out.println("请输入其中一个数字:");
  10. String oneNumber = scanner.nextLine();
  11. System.out.println("输入的数字是:" + oneNumber);
  12. System.out.println("请输入另外一个数字:");
  13. String anotherNumber = scanner.nextLine();
  14. System.out.println("输入的另外一个数字是:" + anotherNumber);
  15. scanner.close();
  16. //todo:oneNumber 和 anotherNumber 需要验证是否是数字,这里省略
  17. Double one = Double.parseDouble(oneNumber);
  18. Double another = Double.parseDouble(anotherNumber);
  19. Double result = 0d;
  20. if(operateNum.equals("1")) {
  21. result = one + another;
  22. }else if(operateNum.equals("2")) {
  23. result = one - another;
  24. }else if(operateNum.equals("3")) {
  25. result = one * another;
  26. }else if(operateNum.equals("4")) {
  27. if(another.equals(0d)) {
  28. System.out.println("除数不能为0");
  29. return;
  30. }
  31. result = one / another;
  32. }
  33. System.out.println("计算的结果是:" + result);
  34. }
  35. }

搞定了,心想:

总算写完了,老大还没找我,反正写完了,休息一会,聊聊天,逛逛网页。

几分钟过去了…

不行,我要表现的积极些,不能老大找我,我才汇报情况,我得主动出击,去告诉一下我这的情况。

我向老大的工位走去…

我:

老大,东西弄完了,你看下行不行。

我向老大演示了一下,老大说道:

老大:

功能是没问题,你把业务逻辑提取一下,就是封装到一个类中,接下来的项目我们要用到。要做到复用。

我:

好的。

我看着代码,想了想:

目前是控制台版本的,如果集成到项目中,可能是 Web 版本,或其他版本的,和现在的区别就是获取用户输入的信息的方式不同而已。计算逻辑还是一样的,把一样的逻辑提取出来就可以了。

想明白了,动手。

新建了一个计算器类:

  1. package SimplePattern02;
  2. public class Calculator {
  3. public Double getResult(String oneNumber,String anotherNumber,String operateNum) throws Exception {
  4. //对 operateNum 的验证略(非空验证,值为1,2,3,4其中一个值的验证)
  5. //todo:oneNumber 和 anotherNumber 需要验证是否是数字,这里省略
  6. Double one = Double.parseDouble(oneNumber);
  7. Double another = Double.parseDouble(anotherNumber);
  8. Double result = 0d;
  9. if(operateNum.equals("1")) {
  10. result = one + another;
  11. }else if(operateNum.equals("2")) {
  12. result = one - another;
  13. }else if(operateNum.equals("3")) {
  14. result = one * another;
  15. }else if(operateNum.equals("4")) {
  16. if(another.equals(0d)) {
  17. throw new Exception("除数不能为0");
  18. }
  19. result = one / another;
  20. }
  21. return result;
  22. }
  23. }

这样控制台的部分代码就简化了很多:

  1. package SimplePattern02;
  2. import java.util.Scanner;
  3. public class Program {
  4. public static void main(String[] args) {
  5. Scanner scanner = new Scanner(System.in);
  6. System.out.println("目前支持 加、减、乘、除 四种运算 \r加法请输入1,减法请输入2,乘法请输入3,除法请输入4。");
  7. System.out.println("请选择算法:");
  8. String operateNum = scanner.nextLine();
  9. System.out.println("请输入其中一个数字:");
  10. String oneNumber = scanner.nextLine();
  11. System.out.println("输入的数字是:" + oneNumber);
  12. System.out.println("请输入另外一个数字:");
  13. String anotherNumber = scanner.nextLine();
  14. System.out.println("输入的另外一个数字是:" + anotherNumber);
  15. scanner.close();
  16. Calculator cal = new Calculator();
  17. Double result = 0d;
  18. try {
  19. result = cal.getResult(oneNumber, anotherNumber, operateNum);
  20. } catch (Exception e) {
  21. System.out.println(e.getMessage());
  22. return;
  23. }
  24. System.out.println("计算结果为:" + result);
  25. }
  26. }

搞定后,我又去找老大汇报。

我:

老大,我搞完了,你再看下。

老大:

好,我看下。嗯…. 目前而言,差不多了。
你这个计算器类下的业务逻辑还不算复杂,
你这里用到了4个if判断,现在每个判断里面也就1行代码。所以,目前就可以了。
后面如果变复杂的话,你就还需要优化了。比如说,如果你每个if下面都10几行代码,那这个计算器类就显得过于复杂了。这时候,你就可以把每个if的业务逻辑抽离出来了。

我想了想。先提前抽离一下,当需要抽离的时候,自己好轻车熟路。

于是,我将4个if抽离成了4个业务逻辑,加法运算,减法运算,乘法运算,除法运算。
分别为每个运算定义了一个类。这些类都实现一个名为“运算”的接口。

接口

  1. package SimplePattern03;
  2. public interface IOperation {
  3. Double getResult() throws Exception;
  4. }

加法运算

  1. package SimplePattern03;
  2. public class OperationAdd implements IOperation {
  3. private Double one;
  4. private Double another;
  5. public Double getOne() {
  6. return one;
  7. }
  8. public void setOne(Double one) {
  9. this.one = one;
  10. }
  11. public Double getAnother() {
  12. return another;
  13. }
  14. public void setAnother(Double another) {
  15. this.another = another;
  16. }
  17. @Override
  18. public Double getResult() {
  19. return one + another;
  20. }
  21. }

减法运算

  1. package SimplePattern03;
  2. public class OperationSub implements IOperation {
  3. private Double one;
  4. private Double another;
  5. public Double getOne() {
  6. return one;
  7. }
  8. public void setOne(Double one) {
  9. this.one = one;
  10. }
  11. public Double getAnother() {
  12. return another;
  13. }
  14. public void setAnother(Double another) {
  15. this.another = another;
  16. }
  17. @Override
  18. public Double getResult() {
  19. return one - another;
  20. }
  21. }

乘法运算

  1. package SimplePattern03;
  2. public class OperationMul implements IOperation {
  3. private Double one;
  4. private Double another;
  5. public Double getOne() {
  6. return one;
  7. }
  8. public void setOne(Double one) {
  9. this.one = one;
  10. }
  11. public Double getAnother() {
  12. return another;
  13. }
  14. public void setAnother(Double another) {
  15. this.another = another;
  16. }
  17. @Override
  18. public Double getResult() {
  19. return one * another;
  20. }
  21. }

除法运算

  1. package SimplePattern03;
  2. public class OperationDiv implements IOperation {
  3. private Double one;
  4. private Double another;
  5. public Double getOne() {
  6. return one;
  7. }
  8. public void setOne(Double one) {
  9. this.one = one;
  10. }
  11. public Double getAnother() {
  12. return another;
  13. }
  14. public void setAnother(Double another) {
  15. this.another = another;
  16. }
  17. @Override
  18. public Double getResult() throws Exception {
  19. if(another.equals(0d)) {
  20. throw new Exception("除数不能为0");
  21. }
  22. return one / another;
  23. }
  24. }

工厂模式

四个逻辑出来了,这样计算器类中只是根据不同的情况来创建不同的对象实例即可。我把这个根据不同情况创建实例的任务也分离出去吧

  1. package SimplePattern03;
  2. public class OperationFactory {
  3. public static IOperation getOperation(Double one,Double another, String operateNum) {
  4. IOperation operation = null;
  5. if(operateNum.equals("1")) {
  6. OperationAdd oper = new OperationAdd();
  7. oper.setOne(one);
  8. oper.setAnother(another);
  9. operation = oper;
  10. }else if(operateNum.equals("2")) {
  11. OperationSub oper = new OperationSub();
  12. oper.setOne(one);
  13. oper.setAnother(another);
  14. operation = oper;
  15. }else if(operateNum.equals("3")) {
  16. OperationMul oper = new OperationMul();
  17. oper.setOne(one);
  18. oper.setAnother(another);
  19. operation = oper;
  20. }else if(operateNum.equals("4")) {
  21. OperationDiv oper = new OperationDiv();
  22. oper.setOne(one);
  23. oper.setAnother(another);
  24. operation = oper;
  25. }
  26. return operation;
  27. }
  28. }

这里的 OperationFactory 就是简单工厂模式。

这样,计算器类就变成这样了。

  1. package SimplePattern03;
  2. public class Calculator {
  3. public Double getResult(String oneNumber,String anotherNumber,String operateNum) throws Exception {
  4. //对 operateNum 的验证略(非空验证,值为1,2,3,4其中一个值的验证)
  5. //todo:oneNumber 和 anotherNumber 需要验证是否是数字,这里省略
  6. Double one = Double.parseDouble(oneNumber);
  7. Double another = Double.parseDouble(anotherNumber);
  8. Double result = 0d;
  9. IOperation oper = OperationFactory.getOperation(one, another, operateNum);
  10. result = oper.getResult();
  11. return result;
  12. }
  13. }

这样,以后哪个运算逻辑要修改,只改对应的类即可。增加了运算逻辑,也就再新增一个运算类即可。维护起来简单多了。

扫码分享
版权说明
作者:SQBER
文章来源:http://www.sqber.com/articles/simple-factory-pattern.html
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。