Skip to content

5. 工厂方法模式

Landy.Liu edited this page May 18, 2019 · 1 revision

工厂方法模式(Factory)允许我们只依赖于抽象接口就能创建出具体对象的实例,所以在开发中,如果具体类是高度易变的,那么该模式就非常有用。

5.1 概念

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

5.2 特点

  1. 良好的封装性,代码结构清晰。
  2. 扩展性好,比如增加一个“产品类”的情况下,只要适当修改工厂类或者扩展出一个工厂类即可。
  3. 屏蔽“产品类”,工厂只关心产品的接口,只要接口不变,系统的上层模块就不会发生变化。
  4. 工厂方法是典型的解耦框架。

5.3 工厂方法模式的扩展

5.3.1 简单工厂模式

又称为静态工厂方法(Static Factory Method)模式,不属于 23 种设计模式之一,它属于类创建型模式(同属于创建型模式的还有工厂方法模式,抽象工厂模式,单例模式,建造者模式)。 在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

5.3.1.1 应用场景

简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。 Spring 中的 BeanFactory 就是简单工厂模式的体现,根据传入一个唯一的标识来获得 Bean 对象,但 是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。

5.3.2 升级为多个工厂类

工厂方法模式把简单工厂模式的内部逻辑判断移到了客户端,把每个“产品类”的实现方式都定义一个工厂类的方式。

5.3.2.1 应用场景

通常由应用程序直接使用 new 创建新的对象,为了将对象的创建和使用相分离,采用工厂模 式,即应用程序将对象的创建及初始化职责交给工厂对象。 一般情况下,应用程序有自己的工厂对象来创建 Bean.如果将应用程序自己的工厂对象交给 Spring 管 理,那么 Spring 管理的就不是普通的 Bean,而是工厂 Bean。

5.3.3 替代单例模式

单例模式的核心是只在内存中保存一个对象,通过工厂方法模式也可以只在内存中生成一个对象。

public class SingletonFactory {

    private static Singleton singleton;

    static {
        try {
            Class cl = Class.forName(Singleton.class.getName());
            //获得无参构造
            Constructor constructor = cl.getDeclaredConstructor();
            //设置无参构造是可访问的
            constructor.setAccessible(true);
            //实例化
            singleton = (Singleton) constructor.newInstance();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static Singleton getSingleton() {
        return singleton;
    }

}
5.3.3.1 应用场景

保证一个类仅有一个实例,并提供一个访问它的全局访问点。 Spring 中的单例模式完成了后半句话,即提供了全局的访问点 BeanFactory。但没有从构造器级别去 控制单例,这是因为 Spring 管理的是是任意的 Java 对象。 Spring 下默认的 Bean 均为单例

5.3.4 延迟初始化

延迟初始化:一个对象被消费完毕后,并不立刻释放,工厂类保持其初始状态,等待再次被调用。 延迟初始化是工厂方法模式的一个扩展应用,比如限制一个产品类的最大实例化数量,可以通过工厂类中的Map中已有的对象数量来实现。 比如JDBC的最大连接数量,该数量就是内存中的最大实例化的数量。 延迟加载还可以用在对象初始化比较复杂的情况下,这样可以通过延迟加载降低对象的产生和销毁带来的复杂性。

注:在【设计模式综合运用】中就有用到延迟初始化的功能。

5.4 总结

简单工厂模式和工厂方法模式都封装了对象的创建,它们使得高层策略模块在创建类的实例时无需依赖于这些类的具体实现。但是两种工厂模式之间又有差异:

  1. 简单工厂模式:最大的优点在于工厂类包含了必要的判断逻辑,根据客户端的条件动态地实例化相关的类。但这也是它的缺点,当扩展功能的时候,需要修改工厂方法,违反了开放封闭原则
  2. 工厂方法模式:符合开放封闭原则,但这带来的代价是扩展的时候要增加相应的工厂类,增加了开发量,而且需要修改客户端代码