如果让你写一个简单的计算器,初学者:辣还不简单,看我的:
import java.util.Scanner;
public class MainClass {
public static void main(String[] args) {
System.out.println("请输入第一个操作数:");
Scanner scanner = new Scanner(System.in);
String num1 = scanner.nextLine();
System.out.println("请输入操作符:");
String oper = scanner.nextLine();
System.out.println("请输入第二个操作数:");
String num2 = scanner.nextLine();
double result = 0.0;
if ("+".equals(oper)) {
result = Double.parseDouble(num1) + Double.parseDouble(num2);
} else if ("-".equals(oper)) {
result = Double.parseDouble(num1) - Double.parseDouble(num2);
} else if ("*".equals(oper)) {
result = Double.parseDouble(num1) * Double.parseDouble(num2);
} else if ("/".equals(oper)) {
result = Double.parseDouble(num1) / Double.parseDouble(num2);
} else {
result = -9999;
}
System.out.println(num1 + oper + num2 + "=" + result);
}
}
搞定!!!呵呵。
既然学了设计模式,这样的代码是拿不出手的。如果让你新增一种计算方法,比如乘方运算,你在呢么办,只能再加个else if,这样的代码是没有可扩展性的。而且,一般情况下,main方法中写的主要是方法的调用,具体的业务逻辑的代码是不出现在main方法中的。这么说的话,上面的代码确实需要改进改进了。
我们想想能不能用前面的工厂方法模式呢?首先,加减乘除都是对操作数的计算,最后得到一个结果,我们可以将这个特征抽取出来,定义成一个父类Calculator.
//Calculator.java
public abstract class Calculator {
private double num1;
private double num2;
public double getNum1() {
return num1;
}
public void setNum1(double num1) {
this.num1 = num1;
}
public double getNum2() {
return num2;
}
public void setNum2(double num2) {
this.num2 = num2;
}
public abstract double getResult();
}
然后我们如果我们就创建具体的运算类型继承这个父类即可,下面是加法、减法的实现:
//AddCalculator.java
public class AddCalculator extends Calculator{
@Override
public double getResult() {
return this.getNum1()+this.getNum2();
}
}
//SubCalculator.java
public class SubCalculator extends Calculator{
@Override
public double getResult() {
return this.getNum1()-this.getNum2();
}
}
然后,要想完成计算,我们必须创建相应的计算类型,对吧?想想,我们前面不是学习了简单工厂模式吗?我们可以定义一个工厂,根据传入的操作符类型new出相应的计算类型类呀。所以,下面我们顶一个工厂:
//CalculatorFactory.java
public class CalculatorFactory {
public Calculator getCalclator (String type){
if("+".equals(type)){
return new AddCalculator();
}else if ("-".equals(type)){
return new SubCalculator();
}
return null;
}
}
这样我们main方法中的代码就清爽多了:
public static void main(String[] args) {
System.out.println("请输入第一个操作数:");
Scanner scanner = new Scanner(System.in);
String num1 = scanner.nextLine();
System.out.println("请输入操作符:");
String oper = scanner.nextLine();
System.out.println("请输入第二个操作数:");
String num2 = scanner.nextLine();
double result = 0.0;
CalculatorFactory cf = new CalculatorFactory();
Calculator calc = cf.getCalclator(oper);
calc.setNum1(Double.parseDouble(num1));
calc.setNum2(Double.parseDouble(num2));
result = calc.getResult();
System.out.println(num1 + oper + num2 + "=" + result);
}
现在,我们如果需要添加一个乘方运算,main方法需要改动吗?不需要。我们只要添加一个乘方运算的类继承自Calculator类,然后在CalculatorFactory 中添加一个else if判断,返回相应的计算类型实例即可。
是不是现在的代码比以前好多了。但是,你有木有觉得还不爽,每次都得改工厂中的代码,是不是很不爽,这违反了”封闭”的原则。是的,我们不还学了工厂方法模式吗?
我们可以将工厂做成一个接口,然后让特定的运算类型工厂实现这个接口,这样的话,即使增加新的运算类型,我们只要新建这个特殊类型的工厂即可。
所以,我们先修改CalculatorFactory,将其做成一个接口。
//CalculatorFactory.java
public interface CalculatorFactory {
public Calculator getCalclator ();
}
然后派生出具体的类型工厂:
//AddFactory.java
public class AddFactory implements CalculatorFactory{
@Override
public Calculator getCalclator() {
return new AddCalculator();
}
}
//SubFactory.java
public class SubFactory implements CalculatorFactory{
@Override
public Calculator getCalclator() {
// TODO Auto-generated method stub
return new SubCalculator();
}
}
这样,我们在main方法中就可以这么调用:(乘除方法就没实现了,只是先加减,各位看官懂意思就好。)
public static void main(String[] args) {
System.out.println("请输入第一个操作数:");
Scanner scanner = new Scanner(System.in);
String num1 = scanner.nextLine();
System.out.println("请输入操作符:");
String oper = scanner.nextLine();
System.out.println("请输入第二个操作数:");
String num2 = scanner.nextLine();
double result = 0.0;
CalculatorFactory cf = null;
if ("+".equals(oper)) {
cf = new AddFactory();
Calculator add = cf.getCalclator();
add.setNum1(Double.parseDouble(num1));
add.setNum2(Double.parseDouble(num2));
result = add.getResult();
} else if ("-".equals(oper)) {
cf = new SubFactory();
Calculator add = cf.getCalclator();
add.setNum1(Double.parseDouble(num1));
add.setNum2(Double.parseDouble(num2));
result = add.getResult();
} else if ("*".equals(oper)) {
result = Double.parseDouble(num1) * Double.parseDouble(num2);
} else if ("/".equals(oper)) {
result = Double.parseDouble(num1) / Double.parseDouble(num2);
} else {
result = -9999;
}
System.out.println(num1 + oper + num2 + "=" + result);
}
可能会有人说,那么你新增加一种运算类型,不还是修改main方法吗,是的这个是不可以避免的,但是,修改main方法中的代码比修改底层实现代码要强吧,你觉得呢?现在只要新增加一种运算类型,只要增加一个实现这个类型的算法(继承子Calculator),然后创建一个实例化这个算法的工厂接口(实现CalculatorFactory接口)。