文章目录
- 模板方法模式 (Template Method Pattern)
- 原理
- 优点
- 缺点
- 示例代码
- 场景描述
- 1. 定义抽象类
- 2. 创建具体类
- 3. 客户端代码
- 输出结果
- UML 类图
- 钩子方法
- 使用场景
- 优化与扩展
- 小结
模板方法模式 (Template Method Pattern)
模板方法模式是一种 行为型设计模式,它定义了一个操作的骨架,将具体的实现延迟到子类。通过模板方法模式,子类可以在不改变骨架的情况下重新定义某些步骤。
原理
- 核心思想:
- 在一个方法中定义算法的框架,将具体实现留给子类。
- 提取公共逻辑到父类中,便于代码复用。
- 适用场景:
- 一些操作步骤是固定的,但某些步骤需要由子类定制。
- 存在多个类有类似的行为,需要复用相同的逻辑。
- 参与角色:
- AbstractClass(抽象类):定义模板方法和抽象方法,模板方法给出逻辑骨架。
- ConcreteClass(具体类):实现抽象方法,提供特定步骤的具体逻辑。
优点
- 代码复用:将通用逻辑提升到父类。
- 灵活扩展:子类可以灵活定制具体实现。
- 封装不变部分:将变化部分交由子类处理。
缺点
- 增加复杂性:引入了继承关系。
- 子类数量增加:不同实现需要创建多个子类。
示例代码
场景描述
以咖啡和茶的制作过程为例。两者的制作过程大致相同,但某些步骤不同。
1. 定义抽象类
// 抽象类
public abstract class Beverage {
// 模板方法,定义制作流程
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
if (addCondimentsHook()) { // 使用钩子方法
addCondiments();
}
}
// 通用方法:烧水
private void boilWater() {
System.out.println("Boiling water...");
}
// 通用方法:倒入杯中
private void pourInCup() {
System.out.println("Pouring into cup...");
}
// 抽象方法:冲泡
protected abstract void brew();
// 抽象方法:添加调料
protected abstract void addCondiments();
// 钩子方法:是否需要添加调料
protected boolean addCondimentsHook() {
return true; // 默认需要添加调料
}
}
2. 创建具体类
// 咖啡类
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("Brewing coffee...");
}
@Override
protected void addCondiments() {
System.out.println("Adding sugar and milk...");
}
}
// 茶类
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("Steeping tea leaves...");
}
@Override
protected void addCondiments() {
System.out.println("Adding lemon...");
}
// 重写钩子方法,不需要添加调料
@Override
protected boolean addCondimentsHook() {
return false;
}
}
3. 客户端代码
public class TemplateMethodExample {
public static void main(String[] args) {
System.out.println("Preparing Coffee:");
Beverage coffee = new Coffee();
coffee.prepareBeverage();
System.out.println("\nPreparing Tea:");
Beverage tea = new Tea();
tea.prepareBeverage();
}
}
输出结果
Preparing Coffee:
Boiling water...
Brewing coffee...
Pouring into cup...
Adding sugar and milk...
Preparing Tea:
Boiling water...
Steeping tea leaves...
Pouring into cup...
UML 类图
+----------------------+
| Beverage |<--------------------+
+----------------------+ |
| + prepareBeverage() | |
| + brew() | (Abstract Method) |
| + addCondiments() | |
| + addCondimentsHook()| |
+----------------------+ |
^ |
| |
+------------------+ +------------------+
| Coffee | | Tea |
+------------------+ +------------------+
| + brew() | | + brew() |
| + addCondiments()| | + addCondiments()|
+------------------+ +------------------+
钩子方法
- 钩子方法是一种可选的方法,允许子类对模板方法的某些行为进行控制。
- 示例中,
addCondimentsHook
用于决定是否添加调料。
使用场景
- 多个子类有类似行为:需要复用通用逻辑。
- 固定流程的实现:如数据处理管道、游戏回合处理等。
- 扩展性需求较高:新增行为只需创建子类。
优化与扩展
- 结合策略模式:
- 可将模板中可变部分抽取为策略,进一步提高灵活性。
- Spring 框架的应用:
- Spring 中大量使用了模板方法模式,如
JdbcTemplate
、RestTemplate
等。
- Spring 中大量使用了模板方法模式,如
小结
- 模板方法模式通过提取公共逻辑,增强了代码复用性。
- 子类只需实现变化部分,避免了重复代码。
- 在需要固定流程和灵活扩展时,模板方法模式是首选方案。