- 现在有一个这样的需求:控制台输入俩个数,并输入运算符,计算并输出结果。上述需求乍一看,特别像一个小型的计算器,记得初学Java时,实现过。
实现一:
- 创建计算器类,控制台输入俩个数以及运算符,通过if条件输出运算结果。
CalClient 类:
public class CalClient {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入第一个数:");
double numbera=sc.nextDouble();
System.out.println("请输入运算符:");
String operator=sc.next();
System.out.println("请输入第二个数:");
double numberb=sc.nextDouble();
if("+".equals(operator)){
System.out.println("运算结果为:"+(numbera+numberb));
}else if("-".equals(operator)){
System.out.println("运算结果为:"+(numbera-numberb));
}else if("*".equals(operator)){
System.out.println("运算结果为:"+(numbera*numberb));
}else if("/".equals(operator)){
if(numberb==0){
System.out.println("除数不能为零");
return;
}
System.out.println("运算结果为:"+(numbera/numberb));
}
}
}
实现效果:
- 思考:这段代码在当时初学编程来说,没有问题,而且结果都能执行成功并输出。但是现在我们再来看是不是有点不太满意的地方,比如:计算控制台逻辑和计算方法逻辑耦合在一起?于是我又优化了一版。
实现二:
- 增加Operation运算类,将计算方法封装到里面,把计算控制台逻辑和计算方法拆开,降低耦合。
Operation类:
public class Operation {
public static Double getOperationResult(double numbera,double numberb,String operator){
Double result=null;
switch (operator){
case "+":
result=numbera+numberb;
break;
case "-":
result=numbera-numberb;
break;
case "*":
result=numbera*numberb;
break;
case "/":
if(numberb==0){
System.out.println("除数不能为零");
return result;
}
result=numbera/numberb;
break;
}
return result;
}
}
CalClient类:
public class CalClient {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入第一个数:");
double numbera=sc.nextDouble();
System.out.println("请输入运算符:");
String operator=sc.next();
System.out.println("请输入第二个数:");
double numberb=sc.nextDouble();
//2.将业务逻辑和界面逻辑分开 解耦
System.out.println("运算结果为:"+(Operation.getOperationResult(numbera,numberb,operator)));
}
}
- 思考:上述代码,虽然将控制台和计算方法解耦,而且这个计算方法类可以做到一定程度上的复用,但是又有了一些新的问题:后续添加或修改计算方法要修改整个Operation类并编译,不安全而且会影响到正常运行的代码。我突然想到了Java是面向对象的,面向对象的三大特性:多态、继承、封装。封装我们用到了,但是多态和继承没有用到,怎么样通过这俩个解决我刚才想到的那个问题呢?我查阅并思考了一下,于是就有了实现三。
实现三:
- 增加类OperationFactory,用于实例化具体的计算实例。增加抽象类AOpeartion,提取统一计算方法。增加计算实现类OperationAdd、OperationSub、OperationMul、OperationDiv。
OperationFactory类:
public class OperationFactory {
public static AOpeartion createOperation(String operator){
AOpeartion opeartion=null;
switch (operator){
case "+":
opeartion=new OperationAdd();
break;
case "-":
opeartion=new OperationSub();
break;
case "*":
opeartion=new OperationMul();
break;
case "/":
opeartion=new OperationDiv();
break;
}
return opeartion;
}
}
AOpeartion类:
public abstract class AOpeartion {
public abstract Double getOperationResult(double numbera, double numberb);
}
OperationAdd类:
public class OperationAdd extends AOpeartion {
@Override
public Double getOperationResult(double numbera, double numberb) {
return numbera+numberb;
}
}
OperationSub类:
public class OperationSub extends AOpeartion {
@Override
public Double getOperationResult(double numbera, double numberb) {
return numbera-numberb;
}
}
OperationMul类:
public class OperationMul extends AOpeartion {
@Override
public Double getOperationResult(double numbera, double numberb) {
return numbera*numberb;
}
}
OperationDiv类:
public class OperationDiv extends AOpeartion {
@Override
public Double getOperationResult(double numbera, double numberb) {
if(numberb==0){
System.out.println("除数不能为零");
return null;
}
return numbera/numberb;
}
}
CalClient类:
public class CalClient {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入第一个数:");
double numbera=sc.nextDouble();
System.out.println("请输入运算符:");
String operator=sc.next();
System.out.println("请输入第二个数:");
double numberb=sc.nextDouble();
//3.利用简单工厂实现 易维护 易复用 易拓展
AOpeartion opeartion=OperationFactory.createOperation(operator);
if(null!=opeartion){
System.out.println("运算结果为:"+(opeartion.getOperationResult(numbera,numberb)));
}else{
System.out.println("运算工厂获取运算类失败");
}
}
}
- 思考:OperationFactory工厂类通过输入的运算符去实例化相应合适的对象,通过多态返回父类的方式实现了计算器的结果。后续如果修改具体的计算方法只要修改具体的计算类即可,不会影响其它计算类。如果增加计算方法,增加实现相应的计算类的具体子类以及增加计算工厂类的switch分支即可。
- 上述就是简单工厂模式的一些内容,大家如果有什么想法可以在评论区交流或者私信我。
计算器相关类结构图