设计模式之工厂模式
工厂模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
我们用工厂模式来实现计算器例子:
//运算方法的通用接口
public interface Operation {
public BigDecimal getResult(BigDecimal numberA, BigDecimal numberB);
}
//具体实现
//加法
public class Add implements Operation{
public BigDecimal getResult(BigDecimal numberA, BigDecimal numberB){
return numberA.add(numberB);
}
}
//减法
public class Subtract implements Operation{
public BigDecimal getResult(BigDecimal numberA, BigDecimal numberB){
return numberA.subtract(numberB);
}
}
//乘法
public class Multiply implements Operation{
public BigDecimal getResult(BigDecimal numberA, BigDecimal numberB){
return numberA.multiply(numberB);
}
}
//除法
public class Divide implements Operation{
public BigDecimal getResult(BigDecimal numberA, BigDecimal numberB){
return numberA.divide(numberB);
}
}
//创建工厂的通用接口:
public interface Factory {
Operation creatOperation();
}
//不同工厂的具体实现
//加法工厂
public class AddFactory implements Factory{
@Override
public Operation creatOperation() {
return new Add();
}
}
//减法工厂
public class SubtractFactory implements Factory{
@Override
public Operation creatOperation() {
return new Subtract();
}
}
//乘法工厂
public class MultiplyFactory implements Factory {
@Override
public Operation creatOperation() {
return new Multiply();
}
}
//除法工厂
public class DivideFactory implements Factory{
@Override
public Operation creatOperation() {
return new Divide();
}
}
//客户端代码
public class Client {
public static void main(String[] args) {
Factory factory = new AddFactory();
Operation add = factory.creatOperation();
System.out.println(add.getResult(BigDecimal.valueOf(10), BigDecimal.valueOf(20)));
}
}
怎么感觉比简单工厂麻烦多了?我们看一下简单工厂的实现:
//创建一个工厂
public class OperationFactory {
public static Operation creatOperation(String operate) {
Operation operation = null;
switch (operate) {
case "+":
operation = new Add();
break;
case "-":
operation = new Subtract();
break;
case "*":
operation = new Multiply();
break;
case "/":
operation = new Divide();
break;
}
return operation;
}
}
//客户端代码
public class Client {
public static void main(String[] args) {
Operation operation;
operation = OperationFactory.creatOperation("+");
System.out.println(operation.getResult(BigDecimal.valueOf(10), BigDecimal.valueOf(20)));
}
}
好像确实是简单工厂更方便一些,它根据客户端的选择条件动态的实例化相关的类。但如果你想添加一种新的运算方式,比如你想添加一个乘方运算,你要创建一个新类实现Operation接口这个是没问题且必须的,还要在简单工厂OperationFactory中添加一个新的case分支,问题就出现在这儿,这个操作违反了开放-封闭原则。
我们再来看工厂模式,同样的例子我们需要添加乘方运算,第一步要创建一个新类实现Operation接口,第二步创建一个新类实现Factory接口。这样我们就不必修改原有的工厂类了。
但是还有一个问题,想想当初我们为什么要用简单工厂模式,我们没用简单工厂模式之前客户端是这样写的:
public class Client {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
BigDecimal A = scanner.nextBigDecimal();
BigDecimal B = scanner.nextBigDecimal();
String str = scanner.next();//操作符
Operation operation = null;
switch (str){
case "+":
operation = new Add();
System.out.println(operation.getResult(A, B));
break;
case "-":
operation = new Subtract();
System.out.println(operation.getResult(A, B));
break;
case "*":
operation = new Multiply();
System.out.println(operation.getResult(A, B));
break;
case "/":
operation = new Divide();
System.out.println(operation.getResult(A, B));
break;
}
}
}
我们为了将逻辑判断从客户端分离而采用了简单工厂模式,但工厂模式实现时客户端需要决定实例化哪一个工厂,它又将逻辑判断移到了客户端,使用工厂模式我们确实不用修改类,但却要修改客户端。
简单工厂模式中,客户端只需要提供操作符,简单工厂会根据客户端的动态选择去实例化相关的类,就像你使用计算器,你只需要按加减乘除就Ok,计算器会做出正确的运算,你不必了解计算器是如何工作的。
工厂模式中,客户端需要决定实例化哪一个工厂类来实现运算类。
工厂模式克服了简单工厂模式违背开放-封闭原则的缺点,但缺点是每增加一种新的运算方式就必须增加一个新的运算工厂,增加了额外的开发量。而且还是没有避免修改客户端的代码。

浙公网安备 33010602011771号