首页 > 代码库 > 简单工厂模式
简单工厂模式
一、举例
做一个非常简单的计算机,实现加减乘除运算即可,大家自然而然的会写出如下代码
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 }
经过上述一系列的修改,也就形成了简单工厂模式。
三、总结
简单工厂模式,即 通过一个‘工厂类’,用于子类返回父类类型或接口类型。
简单工厂模式结束,下一次,将讲解复杂工厂模式。
简单工厂模式