一般情况下,工厂模式可以分为:简单工厂,工厂方法和抽象工厂。而简单工厂、工厂方法原理比较简单,在实际项目中也比较常用。

简单工厂

简单工厂(Simple Factory)就是将代码中负责创建对象的代码抽离到一个独立的类中,让这个类只处理创建对象的细节。

简单工厂是为了让类的职责更加单一、代码更加清晰。简单工厂其实不像一个设计模式,反而比较像一中编程习惯。

来自《Head First 设计模式》的代码实例:

Pizza orderPizza(String type) {
  Pizza pizza;

  // 创建Pizza对象的代码
  if (type.equals("cheese")) {
    pizza = new CheesePizza();
  } else if (type.equals("greek")) {
    pizza = new GreekPizza();
  } else if (type.equals("pepperoni")) {
    pizza = new PepperoniPizza();
  }

  return pizza;
}

我们将创建 Pizza 对象的代码抽离出来到 SimplePizzaFactory 类中。

public class SimplePizzaFactory {
  public Pizza createPizza(String type) {
    Pizza pizza = null;

    if (type.equals("cheese")) {
      pizza = new CheesePizza();
    } else if (type.equals("greek")) {
      pizza = new GreekPizza();
    } else if (type.equals("pepperoni")) {
      pizza = new PepperoniPizza();
    }

    return pizza;
  }
}

再重新修改一下 Pizza 商店代码。

public class PizzaStore {
  SimplePizzaFactory factory;

  public PizzaStore(SimplePizzaFactory factory) {
    this.factory = factory;
  }

  public Pizza orderPizza(String type) {
    Pizza pizza;

    // 通过使用简单工厂来创建披萨
    pizza = factory.createPizza(type);

    return pizza;
  }
}

工厂方法

当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂。

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

img

工厂方法的代码示例:https://github.com/chesterchenn/HFDP/tree/master/src/chapterd/b

使用工厂模式的情况

当创建逻辑比较复杂,我们就考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。何为创建逻辑比较复杂呢?下面两种情况:

  • 第一种情况:类似规则配置解析的例子,代码中存在 if-else 分支判断,动态地根据不同的类型创建不同的对象。针对这种情况,我们就考虑使用工厂模式,将这一大坨 if-else 创建对象的代码抽离出来,放到工厂类中。

  • 还有一种情况,尽管我们不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,比如前面提到的要组合其他类对象,做各种初始化操作。在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中。

工厂方法与简单工厂的差异

工厂方法的子类的确看起来很像简单工厂。简单工厂把全部事情,在一个地方都处理完了,然而工厂方法却是创建一个框架,让子类决定要如何实现。简单工厂可以将对象的创建封装起来,但是不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

DI 容器

DI 容器叫依赖注入容器(Dependency Injection Container),也叫依赖注入框架。

DI 容器底层的设计思路是基于工厂模式的。DI 容器相当于一个大的工厂类,负责在程序启动的时候,根据配置事先创建好对象。当应用程序需要使用某个类对象的时候,直接从容器中获取即可。一个工厂类只负责某个类对象或者一组相关类的对象的创建,而 DI 容器负责的是整个应用中所有类对象的创建。

DI 容器的核心功能

DI 容器的核心功能一般有三个:配置解析,对象创建和对象生命周期管理。

配置解析

将需要由 DI 容器创建的类对象和创建类对象的必要信息,放到配置文件中。容器读取配置文件,根据配置文件提供的信息来创建对象。

对象创建

我们将所有的类对象创建放到一个工厂类中完成就可以了,比如 BeansFactory。避免每个类的创建一个工厂类,导致的类个数成倍增加。

对象的生命周期管理

简单工厂模式有两种实现方式,一种是每次都返回新创建的对象,另一种是每次都返回同一个事先创建好的对象,也就是所谓的单例对象。可以配置对象是否支持懒加载,还可以配置对象的 init-method 和 destroy-method 方法。

抽象工厂

抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。

img

其他

大部分工厂类都是以“Factory”结尾,工厂类中的创建对象的方法一般都是 create 开头,但都不是必须的。

参考链接