工厂方法模式(五)

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

之前写过一篇简单工厂模式,其中有一个计算器的例子,那么工厂方法模式和简单工厂模式有什么区别呢?

简单工厂VS工厂方法:

在简单工厂模式中,如果要增加一个功能需要修改工厂类,违背了开放-封闭原则,工厂方法模式在简单工厂模式上新增加了一个工厂,用来生产简单工厂类,这样整个工厂和产品体系都没有变化,只有扩展的变化,这样就符合开放-封闭原则了。

简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据客户端选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

比如在简单工厂模式——计算器中,让客户端不管该用哪个类的实例,只需要把 '+' 给工厂,工厂自己就给出了相应的实例,客户端只需要去运算就可以了,不同的实例会实现不同的运算。

但问题也就在这里:如果要增加一个‘求M的N次方’的功能,就需要给工厂类的‘case’分支加条件,修改了原有的类,这就等于说我们不仅对扩展开放了,对修改也开放了,这就违背了开放-封闭原则。

既然这个工厂类与分支耦合,要消除这种耦合,根据依赖倒转原则,我们把工厂类抽象出一个接口,这个接口只有一个方法,就是创建抽象产品的工厂方法。然后,所有的要生产具体类的工厂,就去实现这个接口,这样,一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体的生成对象的工厂,于是我们要增加‘求M的N次方’的功能时,就不需要更改原有工厂类了,只需要增加此功能的运算类和相应的工厂就可以了。 这样整个工厂和产品体系其实都没有修改的变化,而只是扩展的变化,这就完全符合了开放-封闭原则的精神。

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码进行。你想要加功能,本来是改工厂类的,而现在是修改客户端!

工厂方法模式实现:

(其中用到了简单工厂模式中的类)

工厂接口

public interface IFactory {
    Operation createOperation();
}

加法工厂

public class AddFactory implements IFactory {
    @Override
    public Operation createOperation() {
        // 返回加法操作类实例
        return new OperationAdd();
    }
}

减法工厂

public class SubFactory implements IFactory {
    @Override
    public Operation createOperation() {
        // 返回减法操作类实例
        return new OperationSub();
    }
}

乘法工厂

public class MulFactory implements IFactory {
    @Override
    public Operation createOperation() {
        // 返回乘法操作类实例
        return new OperationMul();
    }
}

除法工厂

public class DivFactory implements IFactory {
    @Override
    public Operation createOperation() {
        // 返回除法操作类实例
        return new OperationDiv();
    }
}

客户端代码测试类:

public class FactoryTest {
    public static void main(String[] args) throws Exception {
        IFactory factory = new AddFactory();
        Operation operation = factory.createOperation();
        operation.setNumberA(10);
        operation.setNumberB(20);
        double result = operation.getResult();
        System.out.println(result);
    }
}

OutPut:30.0

总结:

工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点,他们都是集中封装了对象的创建,使得要更换对象时,不需要做大的改动就能实现,降低了客户程序与产品对象的耦合。过程方法就是简单工厂模式的进一步抽象和推广。但缺点是由于每加一个产品,就需要加一个产品的工厂类,增加了额外的开发量。利用反射可以解决避免分支判断的问题。这个后面再说。

代码下载地址:https://gitee.com/nisen6477/design-patterns.git

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章