您的位置:首页 > 编程语言 > Java开发

设计模式学习之简单工厂模式

2017-05-15 09:02 459 查看
先说一个简单的案例:

实现一个控制台程序,输入两个数字和一个运算符,输出其计算结果。

案例很简单

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;
}
}
}


但是这样写真的很好吗?java语言的面向对象的优越性就这样放弃了??这样算是业务逻辑和界面逻辑分离了???
基于上述考虑我们可以对这个案例进行重新设计

先考虑业务与逻辑的分离:

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();
}

}
}

从上述的例子中不难看出

简单工厂模式解决的问题是:如何根据需要实例化合适的类

其核心思想:用一个专门的类去产生实例

优缺点分析:

优点:

工厂类是整个模式的关键所在。

包含必要的判断逻辑,能够根据外界给定的信息,决定究竟应该创建哪个具体类的对象。

用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的。

有利于整个软件体系结构的优化。

缺点:

工厂类集中了所有实例的创建逻辑,这就直接导致一旦这个工厂出了问题,所有的客户端都会受到牵连;

简单工厂模式的产品室基于一个共同的抽象类或者接口,这样一来,但产品的种类增加的时候,

即有不同的产品接口或者抽象类的时候,工厂类就需要判断何时创建何种种类的产品,

这就和创建何种种类产品的产品相互混淆在了一起,违背了单一职责,导致系统丧失灵活性和可维护性。

而且更重要的是,简单工厂模式违背了“开放封闭原则”,就是违背了“系统对扩展开放,对修改关闭”的原则,

因为当我新增加一个产品的时候必须修改工厂类,相应的工厂类就需要重新编译一遍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息