先说一个简单的案例:
实现一个控制台程序,输入两个数字和一个运算符,输出其计算结果。
案例很简单
Class Main{
public static void main(String args){
Scanner scan = new Scanner(System.in);
System.out.print("请输入数字A:");
double numberA = scan.nextDouble();
System.out.print("请输入操作符(+ - * /):");
String operate = scan.next();
System.out.print("请输入数字B:");
double numberB = scan.nextDouble();
scan.close();
switch(operate){
case "+":
System.out.println("计算结果是"+(numberA+numberB));
break;
case "-":
System.out.println("计算结果是"+(numberA-numberB));
break;
case "*":
System.out.println("计算结果是"+(numberA*numberB));
break;
case "/":
System.out.println("计算结果是"+(numberA/numberB));
break;
default:
System.out.println("操作符有误");
break;
}
}
}
基于上述考虑我们可以对这个案例进行重新设计
先考虑业务与逻辑的分离:
Class Main{
public static void main(String args){
Scanner scan = new Scanner(System.in);
System.out.print("请输入数字A:");
double numberA = scan.nextDouble();
System.out.print("请输入操作符(+ - * /):");
String operate = scan.next();
System.out.print("请输入数字B:");
double numberB = scan.nextDouble();
scan.close();
Operate op = new Operate(numberA, numberB, operate);
System.out.println("计算结果是"+op.getResult());
}
}
class Operate{
private double numberA;
private double numberB;
private String operate;
public Operate(double numberA, double numberB, String operate){
this.numberA = numberA;
this.numberB = numberB;
this.operate = operate;
}
public double getResult(){
switch(operate){
case "+":
return (numberA+numberB);
break;
case "-":
return (numberA-numberB);
break;
case "*":
return(numberA*numberB);
break;
case "/":
return (numberA/numberB);
break;
default:
break;
}
}
}
使用面向对象的三大特性:
public abstract class Operator {
private double numberA;
private double numberB;
public double getNumberA() {
return numberA;
}
public void setNumberA(double numberA) {
this.numberA = numberA;
}
public double getNumberB() {
return numberB;
}
public void setNumberB(double numberB) {
this.numberB = numberB;
}
public abstract double getResult() throws Exception;
}
class AddOperator extends Operator{
@Override
public double getResult() {
return this.getNumberA()+this.getNumberB();
}
}
class MinusOperator extends Operator{
@Override
public double getResult() {
return this.getNumberA()-this.getNumberB();
}
}
class MultiplyOperator extends Operator{
@Override
public double getResult() {
return this.getNumberA()* this.getNumberB();
}
}
class DivideOperator extends Operator{
@Override
public double getResult() throws Exception {
if(this.getNumberB() == 0)
throw new Exception("除数不能为零");
return this.getNumberA()/ this.getNumberB();
}
}
现在问题是我该如何让程序知道我该实现哪个类完成计算
这里就需要用到简单工厂模式
建立工厂类
public class OperateFactory {
public static Operator createOperator(String operate){
switch (operate) {
case "+":return new AddOperator();
case "-":return new MinusOperator();
case "*":return new MultiplyOperator();
case "/":return new DivideOperator();
default:return null;
}
}
}
在main方法中就可以应用该工厂完成Operate的实例化
class Main{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("输入数字A:");
double numberA = scan.nextDouble();
System.out.print("输入操作符(+ - * / ):");
String operate = scan.next();
System.out.print("输入数字B:");
double numberB = scan.nextDouble();
scan.close();
Operator op = TestFactoryPattern.createOperator(operate);
op.setNumberA(numberA);op.setNumberB(numberB);
try {
System.out.println("计算结果:"+op.getResult());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
从上述的例子中不难看出
简单工厂模式解决的问题是:如何根据需要实例化合适的类
其核心思想:用一个专门的类去产生实例
优缺点分析:
优点:
工厂类是整个模式的关键所在。
包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。
用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。
有利于整个软件体系结构的优化。
缺点:
工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连;
简单工厂模式的产品室基于一个共同的抽象类或者接口,这样一来,但产品的种类增加的时候,
即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,
这就和创建何种种类产品的产品相互混淆在了一起,违背了单一职责,导致系统丧失灵活性和可维护性。
而且更重要的是,简单工厂模式违背了“开放封闭原则”,就是违背了“系统对扩展开放,对修改关闭”的原则,
因为当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。