第4章 工厂方法(Factory Method)模式

    第3章讲述了如何创建单例对象,本章将讲述如何使用工厂方法模式创建普通对象。

    模式是我们在OOP编程中反复看到的模式之一,本章主要内容包括:

    介绍工厂方法模式。

    如何为每个线程创建独立的拷贝。

    静态工厂方法的使用。

    4.1 工厂方法模式

    工厂方法模式是我们常用的模式之一,我们经常在以下情景使用。

    客户类不关心使用哪个具体类,只关心该接口所提供的功能。

    创建过程比较复杂,例如需要初始化其他关联的资源类,读取配置文件等。

    接口有很多具体实现或者抽象类有很多具体子类时,你可能需要为客户代码写一大串if-else逻辑来决定运行时使用哪个具体实现或者具体子类。

    不希望给客户程序暴露过多此类的内部结构,隐藏这些细节可以降低耦合度。

    优化性能,比如缓存大对象或者初始化比较耗时的对象。

    GoF为工厂方法模式给出的定义如下。

    Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

    为创建对象定义一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟至子类。

    工厂方法模式是对实例化过程进行封装而形成的,客户对象无须关心实例化这些类的细节,把它们交给工厂类,在GoF的定义中,为工厂类定义了一个工厂接口。该模式比较简单,我们从UML静态类图着手。

    4.1.1 类图

    我们有一个Product接口,其实现类为ConcreteProduct,工厂负责创建Product对象,这样客户对象就不用关心使用哪个实例以及如何初始化该实例,以后Product实现类如果发生了改变,也不会引起客户代码的改动,只要维护相应的工厂类即可。此模型中,Factory接口是工厂接口,其实现类是ConcreteFactory,如图4-1所示。

    figure_0059_0035

    图4-1

    代码实现

    根据上述的UML图示,不难写出实现代码,如下所示。

    figure_0059_0036

    figure_0060_0037

    代码注解

    Factory接口定义了createProduct()方法来返回Product类型的实例对象,ConcreteFactory类实现了该方法,每次调用都会实例化一个新的ConcreteProduct对象返回。

    工厂方法模式使用起来也非常简单,代码如下所示。

    figure_0060_0038

    如果具体实现类较多,我们可以定义一个参数化的工厂方法,根据不同的输入返回不同的实现子类,代码片段如下。

    figure_0061_0040

    客户对象可以根据需要传入不同的参数获得不同类型的对象。