首页 > 代码库 > 简单工厂模式

简单工厂模式

一、举例

做一个非常简单的计算机,实现加减乘除运算即可,大家自然而然的会写出如下代码

 1 public static void Main(String[] args) {
 2   Scanner scanner = new Scanner(System.in);
 3   System.out.println("请输入数字A:");
 4   double strNumA = scanner.nextDouble();
 5   System.out.println("请选择运算符号(+、-、*、/、)");
 6   String strOperate = scanner.next();
 7   System.out.println("请输入数字C:");
 8   double strNumB = scanner.nextDouble();
 9   double strResult = 0;
10   if ("+".equals(strOperate)) {
11    strResult = strNumA + strNumB;
12   }
13   if ("-".equals(strOperate)) {
14    strResult = strNumA - strNumB;
15   }
16   if ("*".equals(strOperate)) {
17    strResult = strNumA * strNumB;
18   }
19   if ("/".equals(strOperate)) {
20    strResult = strNumA / strNumB;
21   }
22   System.out.println("结果是:" + strResult);
23  }

 

 

二,优化

1,第一步

①由于在判断运算符时,用的是if语句,这意味着每个条件都需要做判断,相当于计算机做了三次无用功。

②没有输入校验,例如,除数不能为零的问题等等

就上述两个问题,做如下修改:

 1 public static void Main(String[] args) {
 2     {
 3       Scanner scanner = new Scanner(System.in);
 4       System.out.println("请输入数字A:");
 5       double strNumA = scanner.nextDouble();
 6       System.out.println("请选择运算符号(+、-、*、/、)");
 7       String strOperate = scanner.next();
 8       System.out.println("请输入数字C:");
 9       double strNumB = scanner.nextDouble();
10       double strResult = 0;
11         switch (strOperate)
12         {
13             case "+":
14              strResult = strNumA + strNumB;
15                 break;
16             case "-":
17              strResult = strNumA - strNumB;
18                 break;
19             case "*":
20              strResult = strNumA * strNumB;
21                 break;
22             case "/":
23                 if (strNumB != 0)
24                 {
25                  strResult = strNumA / strNumB;
26                 }
27                 else
28                 {
29                     System.out.println("除数不能为0");
30                 }
31                 break;
32         }
33         System.out.println("结果是:" + strResult);
34     }

 2、第二步

①上述写的简单的计算器仅仅体现了面向过程的编程,没有体现面向对象的编程

②上述代码使用控制台应用实现的,假如有一天我需要用Web 等实现一模一样的需求,那么,上述代码则需要重新编写,好可怕。

就上述问题,做如下修改:(将业务逻辑与界面分离)

Operation运算类

 1 public class Operation
 2     {
 3         public static double getResult(double numA, double numB, String strOperate)
 4         {
 5             double result = 0;
 6             switch (strOperate)
 7             {
 8                 case "+":
 9                     result = numA + numB;
10                     break;
11                 case "-":
12                     result = numA - numB;
13                     break;
14                 case "*":
15                     result = numA * numB;
16                     break;
17                 case "/":
18                     result = numA / numB;
19                     break;
20             }
21             return result;
22         }
23     }

客户端

 1     public static void Main(String[] args) {
 2     {
 3         try
 4         {
 5             Scanner scanner = new Scanner(System.in);
 6             System.out.println("请输入数字A:");
 7             double strNumA = scanner.nextDouble();
 8             System.out.println("请选择运算符号(+、-、*、/、)");
 9             String strOperate = scanner.next();
10             System.out.println("请输入数字C:");
11             double strNumB = scanner.nextDouble();
12             double strResult = 0;
13             strResult =Operation.getResult(strNumA, strNumB, strOperate);
14             System.out.println("结果是:" + strResult);
15         }
16         catch (Exception ex)
17         {
18             System.out.println("您的输入有错:"+ex.getMessage());
19         }
20     }

这样的话,无论是控制台,还是WEB以及其他应用,只需要调用 Operation 这个类即可了。实现了业务逻辑与界面的分离。这里,也用到了面向对象编程的三大特性之一的封装。

3、第三步

①如果我想增加一种计算方式,例如开根号(sqrt)运算怎么办,只能是修改Operation类,在switch中增加一种情况。

②针对①问题做修改的话,那么另一个问题就来了,我修改Oeration类的时候,之前写好的加减乘除功能全在其中,如果我不小心,或者有意搞破坏,将本来运行的好好的加减乘除功能改掉,怎么办?(此例中仅仅是计算器,如果换做是成熟的产品,或者涉及到资金运算等等的代码,运行的好好的,不可能会让程序员在其中胡作非为的)

针对上述问题,作如下修改:

我可以将加减乘除各种运算分别封装到不同的类里面,这样,就能解决②的问题,每增加一种运算,我就增加一个类,这样①问题也解决了。

首先,将不同的运算抽象出一个共同的类,即父类

 1 public class Operation {
 2     private double numberA;
 3     private double numberB;
 4 
 5     public double getNumberA() {
 6         return numberA;
 7     }
 8 
 9     public void setNumberA(double numberA) {
10         this.numberA = numberA;
11     }
12 
13     public double getNumberB() {
14         return numberB;
15     }
16 
17     public void setNumberB(double numberB) {
18         this.numberB = numberB;
19     }
20 
21     public double getResult() {
22         double result = 0;
23         return result;
24     }
25 
26 }

其次,让不同的运算继承这个父类,然后根据不同的运算,重写父类中的GetResult方法

 1 // 加法类
 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     }
10 
11     // 减法类
12     public class OperationSub extends Operation {
13         @Override
14         public double getResult() {
15             double result = 0;
16             result = numberA - numberB;
17             return result;
18         }
19     }
20 
21     // 乘法类
22     public class OperationMul extends Operation {
23         @Override
24         public double getResult() {
25             double result = 0;
26             result = numberA * numberB;
27             return result;
28         }
29     }
30 
31     // 除法类
32     public class OperationDiv extends Operation {
33         @Override
34         public double getResult() {
35             double result = 0;
36             if (numberB == 0) {
37                 System.out.println("除数不能为0");
38             }
39             result = numberA / numberB;
40             return result;
41         }
42     }

4、第四步

到了简单工厂最核心的地方了。

 这么多的类,客户端该如何用这些类呢,换句话说,客户端如何实例化这些类呢?那么,就需要一个核心的东西——工厂,这个工厂负责给客户端提供他想要的类的实例。我想要实例化什么类,告诉工厂就可以了。

代码如下:

 1 public class OperationFactory
 2     {
 3         public static Operation createOperate(String operate)
 4         {
 5             Operation oper = null;
 6             switch (operate)
 7             {
 8                 case "+":
 9                     oper = new OperationAdd();
10                     break;
11                 case "-":
12                     oper = new OperationSub();
13                     break;
14                 case "*":
15                     oper = new OperationMul();
16                     break;
17                 case "/":
18                     oper = new OperationDiv();
19                     break;
20             }
21             return oper;
22         }
23     }

注意:这个工厂中的方法,返回的是加减乘除这些类的父类.

制造类实例的工厂有了,那么,客户端只需要告诉工厂,给我造一个什么类的实例,然后用这个实例就可以了。

客户端代码如下:

 1 public static void Main(String[] args)
 2     {
 3         Operation oper;
 4         //告诉工厂,给我一个加法类的实例
 5         oper = OperationFactory.createOperate("+");
 6         oper.setNumberA(1);
 7         oper.setNumberB(2);
 8         double result = oper.getResult();
 9         System.out.println(result);
10     }

经过上述一系列的修改,也就形成了简单工厂模式。

三、总结

简单工厂模式,即 通过一个‘工厂类’,用于子类返回父类类型或接口类型。


简单工厂模式结束,下一次,将讲解复杂工厂模式

 

简单工厂模式