模板模式(Template Pattern)是一种行为型设计模式,它定义了一个操作的骨架流程,将某些步骤延迟到子类中实现。核心思想是固定算法结构,灵活定制具体步骤,使得子类可以在不改变算法整体结构的情况下,重写某些特定步骤。
简单来说,模板模式就像 “食谱”—— 食谱规定了做菜的步骤(如准备食材→翻炒→调味→出锅),但具体用什么食材、放多少调料可以由使用者(子类)自行决定。
模版模式的UML表示如下:

在上图中:
- 抽象模板类(AbstractClass):
- 定义
templateMethod():作为算法骨架,按固定顺序调用各个步骤方法。
- 声明抽象方法(
primitiveOperation1()、primitiveOperation2()):这些步骤由子类实现,是算法中可变的部分。
- 提供具体方法(
concreteOperation()):算法中固定不变的步骤,父类直接实现。
- 可选钩子方法(
hook()):默认空实现或基础实现,子类可根据需要重写,用于控制算法流程。
- 具体子类(ConcreteClassA/B):实现父类的抽象方法,定制算法中的可变步骤,也可选择重写钩子方法。
- 客户端:通过抽象模板类调用
templateMethod(),无需关心具体子类,实现对不同算法变体的统一调用。
模板模式的核心价值是封装不变部分,扩展可变部分,常用于框架设计(如 Spring 的JdbcTemplate、Servlet 的doGet/doPost),让框架控制流程,用户只需填充具体业务逻辑。
下面以 “饮品制作流程” 为例,展示模板模式的具体实现。制作咖啡和茶的流程有相似的骨架(煮水→冲泡→倒入杯子→添加调料),但具体步骤的实现不同,适合用模板模式统一流程并差异化实现细节。
首先,我们定义一个抽象的模版类,它定义了饮品制作的流程骨架:
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 33 34 35 36 37 38
| abstract class BeverageMaker {
public final void makeBeverage() { boilWater(); brew(); pourInCup(); if (needCondiments()) { addCondiments(); } }
protected abstract void brew();
protected abstract void addCondiments();
private void boilWater() { System.out.println("煮水至100℃"); }
private void pourInCup() { System.out.println("将饮品倒入杯子"); }
protected boolean needCondiments() { return true; } }
|
制作饮品的抽象步骤是相同的,但是具体执行是有差异的。比如泡茶和泡咖啡的每一个步骤要做的事情是不一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class CoffeeMaker extends BeverageMaker { @Override protected void brew() { System.out.println("用沸水冲泡咖啡粉"); }
@Override protected void addCondiments() { System.out.println("添加牛奶和糖"); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class TeaMaker extends BeverageMaker { @Override protected void brew() { System.out.println("用沸水浸泡茶叶"); }
@Override protected void addCondiments() { System.out.println("添加柠檬"); }
@Override protected boolean needCondiments() { return false; } }
|
客户端调用代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class BeverageShop { public static void main(String[] args) { System.out.println("=== 制作咖啡 ==="); BeverageMaker coffee = new CoffeeMaker(); coffee.makeBeverage();
System.out.println("\n=== 制作茶 ==="); BeverageMaker tea = new TeaMaker(); tea.makeBeverage(); } }
|
使用模板方法的优势在于:
- 代码复用:父类封装了公共步骤(如煮水、倒杯子),避免子类重复实现。
- 流程控制:父类固定算法结构,确保所有子类遵循统一的流程规范(如必须先煮水再冲泡)。
- 灵活扩展:子类通过重写抽象方法和钩子方法,可在不改变流程的前提下定制具体行为。