(《设计模式解析与实战——何红辉,关爱民》读书笔记)
一、定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
比如,生产线的流程,做物理题的固定思路、格式。
二、使用场景
(1)多个子类有公有的方法,并且逻辑基本相同时;
(2)重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现;
(3)重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
三、简单示例
打开计算机的流程是固定的,但对于不同的职业其具体细节是不同的,普通人只需要开机就行,有的人或许还有登录密码,但对于军方来说,登录是很复杂的,各种验证。
/**
* 抽象的Computer:定义了一套算法框架
*/
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("小白的计算机无验证,直接进入系统");
}
/**
* 启动计算机方法,步骤固定。该方法为final,防止算法框架被覆写
*/
public final void startUp() {
System.out.println("-----开机-----");
powerOn();
checkHardware();
loadOS();
login();
System.out.println("-----已开机-----");
}
}
/**
* 具体实现类CoderComputer
*/
public class CoderComputer extends AbstractComputer {
@Override
protected void login() {
System.out.println("普通人进行密码验证");
}
}
/**
* 具体实现类MilitaryComputer
*/
public class MilitaryComputer extends AbstractComputer {
@Override
protected void checkHardware() {
System.out.println("检查硬件防火墙");
}
@Override
protected void login() {
System.out.println("军方人员进行复杂验证");
}
}
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
AbstractComputer computer = new CoderComputer();
computer.startUp();
computer = new MilitaryComputer();
computer.startUp();
}
}
运行结果:
可以看出,子类只需覆写相应的方法来自定义处理。
四、总结
模板方法其实就是“流程封装”。把某个固定的流程封装到一个final函数中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取共用的代码,提升代码的复用率,同时也带来了更好的扩展性。
优点:
(1)封装不变部分,扩展可变部分;
(2)提取公共部分代码,便于维护。
缺点:
模板方法会带来代码阅读的难度,会让用户觉得难以理解。