个人博客

http://www.milovetingting.cn

模板方法模式

模式介绍

在面向对象开发过程中,通常会遇到这样的问题:知道一个算法的关键步骤,并确定了这些步骤的执行顺序,但,某些步骤的具体实现是未知的,如:

  1. 检查代码的正确性

  2. 链接相关的类库

  3. 编译相关代码

  4. 执行程序

对于不同的程序设计语言,上述4个步骤是不一样的,但它们的执行流程是固定的,这类问题的解决方案就是模板方法模式。

模式的定义

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

使用场景

  1. 多个子类公有的方法,并且逻辑基本相同

  2. 重复、复杂的算法,可以将核心算法设计为模板方法,周边的相关代码细节功能由各个子类实现

  3. 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。

简单使用

定义接口

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
public abstract class AbstractComputer {

protected void powerOn() {
System.out.println("开启电源");
}

protected void checkHardware() {
System.out.println("硬件检测");
}

protected void loadOS() {
System.out.println("载入操作系统");
}

protected void login() {
System.out.println("没有密码,直接进入系统");
}

public final void startUp() {
System.out.println("-----开机 START-----");
powerOn();
checkHardware();
loadOS();
login();
System.out.println("-----开机 END-----");
}
}

定义实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ComputerA extends AbstractComputer{

@Override
protected void login() {
System.out.println("验证用户名和密码后开机");
}

}

public class ComputerB extends AbstractComputer {

@Override
protected void checkHardware() {
super.checkHardware();
System.out.println("检查硬件防火墙");
}

@Override
protected void login() {
System.out.println("进行指纹验证");
}

}

调用

1
2
3
4
5
6
7
8
9
10
11
public class Main {

public static void main(String[] args) {
AbstractComputer computerA = new ComputerA();
computerA.startUp();

AbstractComputer computerB = new ComputerB();
computerB.startUp();
}

}

输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
-----开机 START-----
开启电源
硬件检测
载入操作系统
验证用户名和密码后开机
-----开机 END-----
-----开机 START-----
开启电源
硬件检测
检查硬件防火墙
载入操作系统
进行指纹验证
-----开机 END-----

小结

模板方法模式用4个字概括就是:流程封装。就是把固定的流程封装到一个final函数中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取共用的代码,提升代码的复用率,同时也带来了更好的可扩展性。

优点

  1. 封装不变部分,扩展可变部分

  2. 提取公共部分代码,便于维护

缺点

模板方法会带来代码阅读的难度,会让用户觉得难以理解。