设计模式(一)
简单工厂模式
参考图书:大话设计模式(程杰)
如果说让你设计一个简单的计算器,你很容易想到会这么做:
或许你还会想到要进行前后端分离,不然太冗杂,如:
但是这样做,程序员维护起来比较麻烦,比如公司想让你改一下加法,你不小心改了其他运算,这样合不来了。
所以,我们必须要用到面向对象的思想。
理解面向对象:
喝酒唱歌,人生真爽
↓
对酒当歌,人生几何
如果要重新全改完比较麻烦
我们可以将每一个字都作为一个类,当需要改某一个字只需要改动那一个类即可,若要加字,再多写一个类即可。而怎么知道要用哪个类,这就要用到简单工厂了,负责进行new对象。
继续计算器的改进:
Operation类
package 简单工厂模式;
public class Operation {
private double numberA;
private double numberB;
public Operation() {
}
public Operation(double numberA, double numberB) {
this.numberA = numberA;
this.numberB = numberB;
}
public double getNumberA() {
return numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public double getResult(){
double result = 0;
return result;
}
}
OperationAdd类
package 简单工厂模式;
public class OperationAdd extends Operation{
@Override
public double getResult() {
double result=0;
result=getNumberA()+getNumberB();
return result;
}
}
OperationSub类
package 简单工厂模式;
public class OperationSub extends Operation{
@Override
public double getResult() {
double result=0;
result=getNumberA()-getNumberB();
return result;
}
}
OperationMul类
package 简单工厂模式;
public class OperationMul extends Operation{
@Override
public double getResult() {
double result=0;
result=getNumberA()*getNumberB();
return result;
}
}
OperationDiv类
package 简单工厂模式;
public class OperationDiv extends Operation{
@Override
public double getResult() {
double result=0;
if (getNumberB()==0){
System.out.println("除数不能为0");
}
result=getNumberA()/getNumberB();
return result;
}
}
这里就要到工厂类,来通过用户的不同输入,new具体的操作对象(为了调用子类的getResult() 方法)这里也体现了多态(父类型的引用指向子类型的对象)的使用。
OperationFactory类
package 简单工厂模式;
import java.util.Scanner;
public class OperationFactory {
public static Operation createOperate(String operate){
Operation oper=new Operation();
switch (operate){
case "+":
// System.out.println(oper.getNumberA());
// System.out.println(oper.getNumberB());
oper= new OperationAdd();
break;
case "-":
oper=new OperationSub();
break;
case "*":
oper=new OperationMul();
break;
case "/":
oper=new OperationDiv();
break;
}
return oper;
}
}
下面是用户能接触到的界面:
我在此处犯得错误在注释中也做了标明,希望大家不要和一样犯这种错误
package 简单工厂模式;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try{
Scanner scanner=new Scanner(System.in);
System.out.println("要输入的数字A:");
String strNumberA=scanner.nextLine();
System.out.println("要输入的运算字符:");
String strOperate=scanner.nextLine();
System.out.println("要输入的数字B:");
String strNumberB=scanner.nextLine();
//(1)注意这个地方要下先通过工厂类new一个子类对象,而不是自己在这个前端界面new对象
//new对象的任务只需要交给工厂类(从此处进入工厂类)
Operation operation=OperationFactory.createOperate(strOperate);
//(2)再通过set方法 给新new出来的具体操作(+,-,*,/)对象进行赋值,操作Operation类
//若在用户输入时候就new对象赋值,则在工厂类new对象时候,该赋值过的对象就没用了
operation.setNumberA(Integer.parseInt(strNumberA));
operation.setNumberB(Integer.parseInt(strNumberB));
//(3)最后用这个工厂类new出来的具体对象,带着上面的A,B的赋值调用子类重新实现的getResult方法
double result=operation.getResult();
System.out.println(result);
// (×)本人最开始的代码:这样得到的result结果一直为0,原因就出现在
// (×)在这里new完,并通过set方法赋值仅仅是对于当前对象赋值。而工厂类需要重新new对象,
// Operation operation=new Operation();
// Scanner scanner=new Scanner(System.in);
//
// System.out.println("要输入的数字A:");
// String strNumberA=scanner.nextLine();
// operation.setNumberA(Integer.parseInt(strNumberA));
//
// System.out.println("要输入的运算字符:");
// String strOperate=scanner.nextLine();
//
// System.out.println("要输入的数字B:");
// String strNumberB=scanner.nextLine();
// operation.setNumberA(Integer.parseInt(strNumberB));
// (×)(续)这里返回来的对象,A,B的值为0,因为并没有在工厂类中给A,B,赋值
// operation=OperationFactory.createOperate(strOperate);
// double result=operation.getResult();
}catch (Exception e){
System.out.println("除数不能为0");
}
}
}
当然,这个计算器还有很多细节需要改进,比如用户随便输入字符等,本人在此不做更改了,主要学习一下思想。
运行结果如下: