模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,允许子类在不改变算法结构的情况下重写某些步骤的具体实现。
核心思想
抽象类定义模板方法(
final
修饰,防止子类修改算法流程)模板方法中调用多个步骤方法(可以是抽象方法或具体方法)
具体子类实现特定的步骤方法
行为由父类控制,子类只负责实现,子类通过扩展父类,实现更灵活的操作,符合开闭原则。缺点就是导致类个数增多,增加系统复杂度
示例场景:制作饮料
假设我们需要实现咖啡和茶的制作流程,二者步骤类似但具体操作不同:
// 抽象类:定义饮料制作模板
abstract class Beverage {
// 模板方法 (final 防止子类覆盖)
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// 抽象方法:必须由子类实现
protected abstract void brew();
protected abstract void addCondiments();
// 具体方法:通用步骤
private void boilWater() {
System.out.println("烧水");
}
private void pourInCup() {
System.out.println("倒入杯子");
}
// 钩子方法:子类可选择是否覆盖(默认加调料)
protected boolean customerWantsCondiments() {
return true;
}
}
// 具体实现:咖啡
class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("冲泡咖啡粉");
}
@Override
protected void addCondiments() {
System.out.println("加糖和牛奶");
}
// 覆盖钩子方法:不要调料
@Override
protected boolean customerWantsCondiments() {
return false;
}
}
// 具体实现:茶
class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("浸泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("加柠檬");
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Beverage coffee = new Coffee();
coffee.prepareRecipe();
/* 输出:
烧水
冲泡咖啡粉
倒入杯子
*/
Beverage tea = new Tea();
tea.prepareRecipe();
/* 输出:
烧水
浸泡茶叶
倒入杯子
加柠檬
*/
}
}
关键点解析
模板方法:prepareRecipe() 定义了算法骨架
必须实现的步骤:brew() 和 addCondiments() 是抽象方法
可选覆盖的钩子方法:customerWantsCondiments() 提供扩展点
代码复用:通用步骤(boilWater()、pourInCup())在父类实现
应用场景
多个类有相似算法流程,但部分步骤不同
需要控制子类扩展的粒度(如:不允许修改算法顺序)
框架中定义操作流程(如:Spring 的 JdbcTemplate)
该模式通过封装不变部分、扩展可变部分,实现了代码复用与灵活扩展的平衡。
例如:生成PDF模板,有固定的logo位置、固定的表格排版,不固定的就是数据的解析,可以将logo的位置、基础样式放置在父类,将数据的解析放置在子类。