假设有这么一道题,要用一门面向对象的语言实现一个计算器,用户输入两个数和运算符,返回相应的结果。大部分同学应该都会觉得很简单,十分钟不到就能写出来不错的代码。比如:
import java.util.Scanner;
public class main {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
String oper;
double number1,number2;
System.out.println("请输入运算符");
oper = sc.nextLine();
System.out.println("请输入第一个数");
number1 = sc.nextDouble();
System.out.println("请输入第二个数");
number2 = sc.nextDouble();
double result = 0;
switch (oper){
case "+":
result=number1+number2;break;
case "-":
result=number1-number2;break;
case "*":
result=number1*number2;break;
case "/":
if(Math.abs(number2-0.0D)<1e-10){
System.out.println("除数不能为0!");
return;
}
result=number1/number2;
break;
}
System.out.println(result);
}
}
但是,如果还需要处理开根号,是不是就要再加一个case,而且如果在加的时候不小心把别的case给改动了,就会引起程序的错乱,无法得到正常的结果。这就说明这个程序扩展性、灵活性差。另外结果的显示和运算的处理都在同一个类下,耦合性低,不易修改。
因此,需要引入简单工厂模式。
简单工厂模式:定义一个Factory类,可以根据参数的不同返回不同类的实例,被创建的实例通常有共同的父类。
我们需要将每个运算符独自封装成一个类,继承自Operation父类,每次修改只需修改运算符类中的内容,添加运算符的话也只需新建一个子类即可。
子类通过重写getResult方法进行计算。
同时将运算与结果展示分开,在用户输入的类调用运算程序,再将得到的结果进行显示。
首先编写Operation类及每个运算符子类
/**
* @Author: Bhy
* @Date: 2018/11/16
*/
public abstract class Operation {
double numberA;
double numberB;
abstract double getResult() throws Exception;
}
class OperationAdd extends Operation{
@Override
double getResult() {
return numberA + numberB;
}
}
class OperationSub extends Operation{
@Override
double getResult() {
return numberA - numberB;
}
}
class OperationMul extends Operation{
@Override
double getResult() {
return numberA * numberB;
}
}
class OperationDiv extends Operation {
@Override
double getResult() throws Exception{
if(Math.abs(numberA-0.0D)<1e-10){
throw new Exception("被除数不能为0");
}
else{
return numberA / numberB;
}
}
}
创建简单工厂类,能够通过用户输入的运算符返回对应的运算符子类。
/**
* @Author: Bhy
* @Date: 2018/11/16
*/
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;
}
}
在主函数用调用简单工厂类,得到运算结果并输出。
import java.util.Scanner;
/**
* @Author: Bhy
* @Date: 2018/11/16
*/
public class main {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
String operate;
System.out.println("请输入运算符");
operate = sc.nextLine();
Operation operation = OperationFactory.createOperate(operate);
System.out.println("请输入第一个数");
operation.numberA = sc.nextDouble();
System.out.println("请输入第二个数");
operation.numberB = sc.nextDouble();
try{
System.out.println(operation.getResult());
}catch (Exception ex) {
System.out.println("输入有误,请检查");
}
}
}
至此,这个计算器就有了良好的维护性、扩展性和灵活性。当需要加入新的运算符时,只需要编写新的运算符子类并在简单工厂类中添加一个case即可。