[译文]设计模式03 – 工厂方法模式(附代码实例)

原文网址:Factory Method Design Pattern

意图

  • 定义一个用来创建对象的接口,由其子类(实现类)决定哪个类应该被初始化。工厂方法把类的初始化过程延迟到子类里
  • 定义一个虚拟的构造器
  • new 是危险的操作

问题

一个框架需要对其架构模型有一套标准化的操作规范,但对一个单独的应用来说,可以定义不同的作用域对象及其初始化过程。

讨论

工厂方法模式是为了创建对象,就像模板方法模式是为了实现一种算法。接口定义了标准的创建对象的方法(用纯虚拟的标识——如abstract——来修饰创建步骤),然后委托子类去完成创建的具体步骤,并将子类提供给客户端调用。

工厂方法模式使得设计具有更多的可定制化空间,而只是多了一点点复杂性。其他设计模式需要新的类,而它只需要新的操作(方法)。

大家经常使用工厂方法模式作为创建对象的标准方式,但以下情况就没有必要用了:初始化过程不会再改变的类,或者初始化过程被放在很容易被子类覆盖的方法里(如构造函数)。

工厂模式方法和抽象工厂很相似,只是少了那一组相关或类似对象。

工厂模式通常是在基础框架中定义,然后由使用者去实现。

结构

在“四人帮设计模式中”,工厂方法模式和抽象工厂模式有很多重复的地方(见下图)。鉴于此,本文阐述的是当下最流行的实现。

 

Factory_Method_1

现在越来越流行的抽象工厂的实现方式是:定义一个 static 方法返回对象实例。与构造函数不同的是:1)实际返回的可能是某个子类的实例;2)已经存在的实例可能被重复使用,而不是创建一个新的实例;3)工厂方法模式可以有更高辨识度的名字,如 Color.makeRGBColor(float r, float g, float b) 或者Color.makeHSBColor(float h, float s, float b) 。

Factory_Method_2

 

客户端与衍生的子类完全解耦。多态地创建实例变为可能。

Factory_Method_3

 

举例

注模机印证了这种模式。塑料玩具的制造厂商先处理塑料制模粉,然后将其注入指定形状的模具中。玩具类(小汽车、玩偶等)是由模具决定的。

Factory_Method_example

 

核查清单(也可以理解为应用步骤)

  1. 如果有一套运用多态的继承关系,考虑在基类里定义一个静态的工厂方法,来增加动态创建多态实例的能力。
  2. 给工厂方法定义入参,使其能够清楚地知道具体哪个衍生类应该被实例化。
  3. 考虑设计一个“对象池”,使对象的实例可以重复使用而不是简单的创建
  4. 考虑将所有的构造函数改为 private 或 protected 修饰

经验法则

  • 工厂方法的优势在于它可以多次返回同一个实例,或者返回一个子类而不是某个特定的类型。
  • 作为编程语言的设计或风格,有些工厂模式决绝地建议将所有类的构造函数定义为private 或 protected 。一个类大量地创建新对象还是重复地使用老对象,都行,自己决定就好,跟别人无关。
  • new 操作被认为是有害的。请求一个对象和创建一个对象之间是由区别的。new 通常是创建一个对象,且没有封装对象的创建。工厂方法强制封装,并且允许请求一个对象而不需要与创建行为产生不可解的耦合。

(译者注:详细的代码实例请移步 GitHub

加入讨论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据