初探模板方法模式

代码链接

koonchen/design-patterns/template-method

要点

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

如下面类图所示:

cover

上面的类图中,OpenDocument 定义了打开一个文档的每一个主要步骤,它检查该文档是否能被打开,创建与应用相关的 Document 对象,将它加到文档集合中,并且从一个文件中读取该 Document

我们称 OpenDocument 为一个模板方法,一个模板方法用一些抽象的操作定义一个算法,而子类将重定义这些操作以提供具体的行为。Application 的子类将定义检查一个文档是否能够被打开和创建文档的具体算法步骤。

模板方法的适用性:

  • 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
  • 控制子类扩展,模板方法强调 hook 操作,这样就只允许在这些点进行扩展。

模板方法的参与者:

  • AbstractClass : 定义抽象的原语操作,具体的子类将重定义它们以实现一个算法的各步骤。
  • ConcreteClass : 实现原语操作以完成算法中与特定子类相关的步骤。

模板方法的结构:

cover

模板方法的效果:

  • 钩子操作,它提供了缺省的行为,子类可以在必要时进行扩展,一个钩子操作在缺省操作时通常是一个空操作。
  • Factory Method

实现

Java 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
abstract class AbstractClass {
void templateMethod() {
primitiveOperation1();
primitiveOperation2();
}
abstract void primitiveOperation1();
abstract void primitiveOperation2();
}

class ConcreteClass extends AbstractClass {

@Override
void primitiveOperation1() {
System.out.println("primitiveOperation1 method has been used");
}

@Override
void primitiveOperation2() {
System.out.println("primitiveOperation2 method has been used");
}
}

public class TemplateMethodClient {
public static void main(String[] args) {
AbstractClass abstractClass = new ConcreteClass();
abstractClass.templateMethod();
}
}

相关实现:

  • Factory Method : 常常被模板方法调用,上面的 DoCreateDocument 就是一个 Factory Method 。
  • Strategy : 模板方法使用继承来改变算法的一部分。