一、模板设计模式的核心思想

模板设计模式(Template Method Pattern)的核心是 定义一个算法的骨架,将某些步骤延迟到子类中实现,使得子类可以在不改变算法整体结构的情况下,重新定义某些步骤的具体逻辑。

核心要点

  1. 固定流程:父类定义算法的主要步骤(如“烧水→冲泡→倒入杯子→加调料”)。
  2. 可变细节:子类实现具体的步骤(如“如何冲泡茶叶”或“加什么调料”)。
  3. 控制反转:父类控制流程,子类填充细节。

二、Java 实现模板模式的步骤

1. 定义抽象类(模板类)

  • 模板方法:用 final 修饰,定义算法的流程(防止子类覆盖流程)。
  • 抽象方法:用 abstract 修饰,表示必须由子类实现的方法。
  • 具体方法:父类提供默认实现的方法(如公共步骤)。
  • 钩子方法(可选):提供默认逻辑的方法,子类可选择性覆盖(用于控制流程分支)。
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
29
30
31
32
public abstract class AbstractClass {
// 模板方法(final 防止子类覆盖流程)
public final void templateMethod() {
step1();
step2();
step3();
if (hookMethod()) { // 钩子方法控制流程分支
step4();
}
}

// 抽象方法(必须由子类实现)
protected abstract void step2();

// 具体方法(默认实现)
private void step1() {
System.out.println("执行步骤1");
}

// 钩子方法(可选覆盖)
protected boolean hookMethod() {
return true; // 默认执行步骤4
}

// 另一个具体方法
private void step3() {
System.out.println("执行步骤3");
}

// 抽象方法
protected abstract void step4();
}

2. 定义具体子类

子类继承抽象类,并实现其抽象方法。可以覆盖钩子方法以改变流程。

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
29
public class ConcreteClassA extends AbstractClass {
@Override
protected void step2() {
System.out.println("ConcreteClassA 实现的步骤2");
}

@Override
protected void step4() {
System.out.println("ConcreteClassA 实现的步骤4");
}

// 覆盖钩子方法,禁止执行步骤4
@Override
protected boolean hookMethod() {
return false;
}
}

public class ConcreteClassB extends AbstractClass {
@Override
protected void step2() {
System.out.println("ConcreteClassB 实现的步骤2");
}

@Override
protected void step4() {
System.out.println("ConcreteClassB 实现的步骤4");
}
}

3. 使用模板模式

通过调用模板方法触发算法流程:

1
2
3
4
5
6
7
8
9
public class Client {
public static void main(String[] args) {
AbstractClass instanceA = new ConcreteClassA();
instanceA.templateMethod();

AbstractClass instanceB = new ConcreteClassB();
instanceB.templateMethod();
}
}

输出结果

1
2
3
4
5
6
7
8
执行步骤1
ConcreteClassA 实现的步骤2
执行步骤3

执行步骤1
ConcreteClassB 实现的步骤2
执行步骤3
ConcreteClassB 实现的步骤4

三、Java 实现的关键细节

1. final 关键字的作用

  • 模板方法必须用 final 修饰:防止子类覆盖算法的整体流程。
  • 示例:public final void templateMethod() { ... }

2. 抽象方法与具体方法

  • 抽象方法:由子类实现差异化逻辑(如 step2()step4())。
  • 具体方法:父类提供公共逻辑(如 step1()step3())。

3. 钩子方法(Hook Method)

  • 用途:允许子类影响模板方法的流程(如控制是否执行某一步骤)。
  • 实现:在父类中提供默认实现,子类可选择覆盖。
  • 示例:protected boolean hookMethod() { return true; }