简单工厂模式:简单的说就是通过传入的参数,动态的生成你需要的类,并调用该类的方法。
也能使你的代码变的易于维护,扩展性好,灵活等等,,
话不多说,来看一段 将普通代码演变成工厂模式的例子
有一段实现计算器的简单代码
public class program2 {
public static void main(String[] args) {
try {
System.out.println("请输入数字A");
Scanner scanner = new Scanner(System.in);
double strNumberA = scanner.nextDouble();
System.out.println("请选择运算符号");
String strOperate = scanner.next();
System.out.println("请输入数字B");
double strNumberB = scanner.nextDouble();
String result = "";
switch (strOperate) {
case "+":
result = String.valueOf(strNumberA + strNumberB);
break;
case "-":
result = String.valueOf(strNumberA - strNumberB);
break;
case "*":
result = String.valueOf(strNumberA * strNumberB);
break;
case "/":
if (strNumberB != 0) {
result = String.valueOf(strNumberA / strNumberB);
} else {
System.out.println("除数不能为0");
}
break;
}
System.out.println(result);
} catch (Exception e) {
System.out.println("你的输入有误:" + e);
}
}
}
恩,乍一看,这段代码命名规范,考虑到了除法的特殊情况,也考虑到了用户输入的是否是数字的问题,没啥毛病呀。
恩,代码是没啥毛病。但是!
1 如果别的地方要复用怎么办?用ctrl+c ctrl+v?这其实是非常不好的编码习惯!因为当你的代码中重复的代码多到一定程度,维护的时候就是一场灾难。
2 假如我需要增加一个开平方根运算,是直接在switch中直接新加一个分支?那么问题就来了,为了添加一个新的运算方法,却要让加减乘除的运算一起参与编译,如果你一不小心把加法改成了减法!这就糟糕了。
第一个问题的解决方案:将加减乘除的业务封装起来
第二个问题的解决方案 : 将加减乘除等运算分离,修改其中一个不影响另外的几个,增加运算算法也不影响其他代码
改进后的代码
//运算类 基类 提取公共属性和方法
public class Operation {
private double strNumberA;
private double strNumberB;
public double getStrNumberA() {
return strNumberA;
}
public void setStrNumberA(double strNumberA) {
this.strNumberA = strNumberA;
}
public double getStrNumberB() {
return strNumberB;
}
public void setStrNumberB(double strNumberB) {
this.strNumberB = strNumberB;
}
/**
* 得到结果
* @return
* @throws Exception
*/
public double getResult() throws Exception {
return 0d;
}
}
/**
* 加法
*/
public class OperationAdd extends Operation {
@Override
public double getResult() {
double result;
result = getStrNumberA() + getStrNumberB();
return result;
}
}
/**
* 减法
*/
public class OperationSub extends Operation {
@Override
public double getResult() {
double result;
result = this.getStrNumberA() - this.getStrNumberB();
return result;
}
}
/**
* 乘法
*/
public class OperationMul extends Operation {
@Override
public double getResult() {
double result;
result = this.getStrNumberA() * this.getStrNumberB();
return result;
}
}
/**
* 除法
*/
public class OperationDiv extends Operation {
@Override
public double getResult() throws Exception {
double result;
if (this.getStrNumberB() == 0) {
throw new Exception("除数不能为0!");
}
result = this.getStrNumberA() / this.getStrNumberB();
return result;
}
}
上述代码使用封装的方式将业务从代码中分离了出来
并用继承的方式实现了各个运算模块互不干扰
那么现在我们如何去实例化对象呢?也就是说到底要实例化谁?将来会不会增加实例化的对象,比如增加开根运算,这是很容易变化的地方!应该考虑用一个单独的类来做这个创建实例的过程,这就是工厂!
/**
* 工厂模式
* 根据用户传入的操作符
* 动态的返回对应的操作对象
*/
public class OperationFactory {
public static Operation createOperate(String operate) {
Operation operation = null;
switch (operate) {
case "+":
operation = new OperationAdd();
break;
case "-":
operation = new OperationSub();
break;
case "*":
operation = new OperationMul();
break;
case "/":
operation = new OperationDiv();
break;
}
return operation;
}
}
通过这个operationFactory类使得我们调用的时候 只要传入对应的operate操作符,程序将通过多态的方式将你想要的operation类返回给你
public class program4 {
public static void main(String[] args) {
System.out.println("请输入数字A");
Scanner scanner = new Scanner(System.in);
double strNumberA = scanner.nextDouble();
System.out.println("请选择运算符号");
String strOperate = scanner.next();
System.out.println("请输入数字B");
double strNumberB = scanner.nextDouble();
//传入对应的操作符 工厂将会实例化对应的operation类并返回
Operation operation = OperationFactory.createOperate(strOperate);
operation.setStrNumberA(strNumberA);
operation.setStrNumberB(strNumberB);
try {
System.out.println(operation.getResult());
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果需要更改 加法 的逻辑 只需要更改对应的 加法类 operationAdd 就可以了 不会影响其他的类 <易维护>
如果需要增加一个算法 只需要添加一个对应的运算子类 并在工厂类的 switch添加新的分支就可以<易扩展>
只需要传入不同的操作符,就能实例化对应的operation类<灵活>
如果需要修改界面 就只要更改界面 与算法没有关系