设计模式之工厂模式

工厂模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

我们用工厂模式来实现计算器例子:

//运算方法的通用接口
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,计算器会做出正确的运算,你不必了解计算器是如何工作的。
工厂模式中,客户端需要决定实例化哪一个工厂类来实现运算类。

工厂模式克服了简单工厂模式违背开放-封闭原则的缺点,但缺点是每增加一种新的运算方式就必须增加一个新的运算工厂,增加了额外的开发量。而且还是没有避免修改客户端的代码。

posted @ 2020-09-27 22:14  xxgbl  阅读(159)  评论(0)    收藏  举报