设计模式----简单工厂模式
工作大半年了,本作者深深的认识到在学校中所学到的知识远远不够工作需求,前两天做的树结构数据和layui树组织结合,明明想法在脑袋里,却怎么也做不出来,查资料,做了整整两天才搞定!对,明明在学校里学过数据结构,也做过树组织,但是两者结合却不会了。所以从今天开始,本作者决定通过看书来补充一下职场知识,先从大话设计模式这本书开始,今天就来简单说一下大话设计模式中的简单工厂模式。
大话设计模式讲的很好,所以我在这里也通过引用一下大话设计模式里的例子讲一下简单工厂模式。通常情况下初学者做一个计算器会怎么做?直接在main函数里让用户在控制台输入两个数字和运算符号,通过switch case判断直接运算输出下结果,代码如下(在看书看到这里的时候我也是这么想的)
package dahua;
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
// TODO Auto-generated method stub
String x = "1";
while(x.equals("1")) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入第一位数字:");
String numberA = scanner.next();
System.out.println("请输入第二位数字:");
String numberB = scanner.next();
System.out.println("请输入要进行的运算(+-*/)");
String operate = scanner.next();
String result = "0";
if(operate.equals("/")&&numberB.equals("0")) {
System.out.println("0不能当除数,请重新输入");
continue;
}
switch (operate) {
case "+":
result=(Integer.parseInt(numberA)+Integer.parseInt(numberB))+"";
break;
case "-":
result=(Integer.parseInt(numberA)-Integer.parseInt(numberB))+"";
break;
case "*":
result=(Integer.parseInt(numberA)*Integer.parseInt(numberB))+"";
break;
case "/":
result=(Integer.parseInt(numberA)/Integer.parseInt(numberB))+"";
break;
default:
System.out.println("请输入正确的的运算符号");
continue;
}
System.out.println("运算结果"+result);
System.out.println("是否继续运算?继续请输入任意1,结束请任意输入");
x = scanner.next();
}
}
}
好家伙,程序是写出来了,也满足的基本的要求!但是程序不说灵活性、复用性、可扩展性,单单的维护性都不满足,java的三大特性封装、继承、多态一个也没用上,java语言的优势没有体现出来!java是一门面向对象的语言,面向对象的好处不说了!我们通过面向对象编程试一下!
package dahua;
import java.util.Scanner;
public class OperateMain {
public static void main(String[] args) {
String x = "1";
while(x.equals("1")) {
Scanner scanner=new Scanner(System.in);
System.out.println("请输入第一位数字:");
String numberA = scanner.next();
System.out.println("请输入第二位数字:");
String numberB = scanner.next();
System.out.println("请输入要进行的运算(+-*/)");
String operate = scanner.next();
if(!operate.equals("+")&&!operate.equals("-")&&!operate.equals("*")&&!operate.equals("/")) {
System.out.println("请输入正确的运算符号");
continue;
}
if(operate.equals("/")&&numberB.equals("0")) {
System.out.println("0不能做除数,请重新输入");
continue;
}
double result = Operate.GetResult(numberA, numberB, operate);
System.out.println("运算结果"+result);
System.out.println("是否继续运算?继续请输入任意1,结束请任意输入");
x = scanner.next();
}
}
}
package dahua;
public class Operate {
public static double GetResult(String numberA,String numberB,String operate) {
String result="0";
switch (operate) {
case "+":
result=(Integer.parseInt(numberA)+Integer.parseInt(numberB))+"";
break;
case "-":
result=(Integer.parseInt(numberA)-Integer.parseInt(numberB))+"";
break;
case "*":
result=(Integer.parseInt(numberA)*Integer.parseInt(numberB))+"";
break;
case "/":
result=(Integer.parseInt(numberA)/Integer.parseInt(numberB))+"";
break;
default:
System.out.println("请输入正确的的运算符号");
break;
}
return 0;
}
}
这样做的好处是业务逻辑和视图界面分开了,降低了程序的耦合性,你改你的视图界面不影响我的逻辑运算,我改我的逻辑运算不影响你的视图界面,不会因为我的逻辑代码和你的视图代码在一块,改的时候不小心动了对方的代码影响程序的运行,而且不仅仅这个视图界面可以使用计算器的逻辑代码,web、安卓、linux等地方都可以使用它。你以为到此就结束了,别开玩笑了,你只用到了面向对象的三大特性之一封装啊,还有继承多态呢!
考虑下一个场景,你写的计算器只有四种运算,如果公司需要添加新运算,而且把任务分配给一个新来的萌新呢?不说他能不能编写出来,随便改改,把你的源程序改动的不能用了,就问你怕不怕,所以单纯的封装耦合性还是比较高,考虑到降低耦合性问题,在此使用继承和封装来试试降低程序的耦合性
package factory;
//运算父类
public class OperateFather {
private double numberA;
private double numberB;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public double getResult() {
double result = 0.0;
return result;
}
}
package factory;
//加法运算
public class OpreateAdd extends OperateFather{
public double getResult() {
double result = getNumberA()+getNumberB();
return result;
}
}
package factory;
//减法运算
public class OpreateSub extends OperateFather{
public double getResult() {
double result = getNumberA()-getNumberB();
return result;
}
}
package factory;
//乘法运算
public class OpreateMul extends OperateFather{
public double getResult() {
double result = getNumberA()*getNumberB();
return result;
}
}
package factory;
//除法运算
public class OpreateDiv extends OperateFather{
public double getResult() {
double result = getNumberA()/getNumberB();
return result;
}
}
写一个父类OperateFather,当下次要添加新运算的时候,直接创建一个新类继承此类,重写一下getResult方法就行,你看这样就不用担心因为扩展而使源程序出现问题了!降低耦合性问题解决了,下面就是怎么用了,这就用到设计模式----简单工厂模式了,代码如下:
package factory;
public class OperationFactory {
public static OperateFather createOperate(String operate) {
OperateFather opr = null;
switch(operate) {
case "+":
opr = new OpreateAdd();
break;
case "-":
opr = new OpreateSub();
break;
case "*":
opr = new OpreateMul();
break;
case "/":
opr = new OpreateAdd();
break;
//程序如需扩展在此添加新的case即可
}
return opr;
}
}
package factory;
import dahua.Operate;
//程序起点main函数
public class OPmain {
public static void main(String[] args) {
String operate = "+";
double numberA = 1;
double numberB = 2;
OperateFather opr = OperationFactory.createOperate(operate);
opr.setNumberA(numberA);
opr.setNumberB(numberB);
double result = opr.getResult();
System.out.println("计算结果是"+result);
}
}
每次扩展写完运算逻辑后,需要在工厂类中添加新case,用到时候只要传入对应的运算符号,工厂类会自动创建相应的运算对象,在用set方法向对象传入数据后,调用getResult方法即可获得运算结果。