云计算百科
云计算领域专业知识百科平台

设计模式-模板方法模式

模板方法模式(Template Method Pattern),定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构,即可重定义该算法的某些特定步骤。

模板方法模式的核心思想是“好莱坞原则”——“不要调用我们,我们会调用你(Don't call us, we'll call you)”。父类定义好一套固定的算法执行流程,而将其中多变的具体环节留给子类去实现,实现了代码复用与流程控制的统一。

优缺点

优点

  • 代码复用,减少冗余: 将公共步骤与算法骨架抽取到父类中,子类只需关注自身特殊的业务逻辑。
  • 锁定流程,规范行为: 父类统筹控制整体算法结构,防止子类无意破坏或修改算法的执行顺序。
  • 符合开闭原则(OCP): 增加新的算法实现只需新增一个子类,扩展方便,不影响原有的父类与其他子类。

缺点

  • 类数量增加: 每一个不同的具体实现都需要定义一个子类,可能导致系统中的类数量膨胀。
  • 反向控制带来阅读成本: 子类方法被父类调用,对于不熟悉继承链的代码阅读者来说,理解代码执行流程相对困难。
  • 骨架修改影响较大: 一旦父类的模板方法结构发生变动,所有子类都会受到波及。

举个例子

制作冲泡饮料(Beverage),整体流程都是固定的:

烧水 -> 冲泡 -> 倒入杯中-> 加调味料

其中 烧开水 和 倒入杯中 是所有饮料通用的步骤;而 冲泡 与 加调味料 则由具体饮料自行决定。此外,还可以通过 “钩子(Hook)” 决定是否要加调味料。

代码实现

// 抽象父类:定义算法骨架
public abstract class Beverage {

// 模板方法:定义整体流程(用 final 修饰,防止子类颠倒或修改步骤)
public final void makeBeverage() {
boilWater();
brew();
pourInCup();
// 通过钩子方法控制是否执行某个步骤
if (customerWantsCondiments()) {
addCondiments();
}
}

// 通用具体步骤 1:烧水
private void boilWater() {
System.out.println("将水烧开到 100℃");
}

// 通用具体步骤 2:倒进杯子
private void pourInCup() {
System.out.println("倒入杯中");
}

// 抽象步骤 1:冲泡(子类必须实现)
protected abstract void brew();

// 抽象步骤 2:加调味料(子类必须实现)
protected abstract void addCondiments();

// 钩子方法(Hook):默认提供标准逻辑,子类可按需重写Override
protected boolean customerWantsCondiments() {
return true;
}
}

// 具体子类 1:咖啡
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("用滤纸萃取咖啡粉");
}

@Override
protected void addCondiments() {
System.out.println("加入牛奶和糖");
}
}

// 具体子类 2:茶(重写钩子,不加调料)
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("用沸水浸泡茶叶");
}

@Override
protected void addCondiments() {
System.out.println("加入柠檬片");
}

// 重写钩子:原味茶不加调味料
@Override
protected boolean customerWantsCondiments() {
return false;
}
}

客户端调用

public class Client {
public static void main(String[] args) {
System.out.println("=== 制作咖啡 ===");
Beverage coffee = new Coffee();
coffee.makeBeverage();

System.out.println("\\n=== 制作原味茶 ===");
Beverage tea = new Tea();
tea.makeBeverage();
}
}

=== 制作咖啡 ===
将水烧开到 100℃
用滤纸萃取咖啡粉
倒入杯中
加入牛奶和糖

=== 制作原味茶 ===
将水烧开到 100℃
用沸水浸泡茶叶
倒入杯中

模板方法模式的组成要素

  • 模板方法(Template Method): 定义在抽象类中的核心方法,封装了算法的大体骨架,通常用 final 修饰防止重写。
  • 抽象方法(Abstract Methods): 由父类声明、子类必须实现的步骤,用于填充算法中个性化的业务逻辑。
  • 具体方法(Concrete Methods): 父类中已经提供好具体实现的方法,供所有子类共享复用。
  • 钩子方法(Hook Methods): 父类提供默认实现(通常为返回 boolean 或空实现),子类可以自由选择是否重写,用以动态控制模板方法的执行分支。
  • 适用场景

    • 固定流程骨架: 多个子类有通用的处理流程,但具体细节不同(例如:数据导入/导出流程、订单结算流程)。
    • 框架开发与扩展点设计: 框架定义好生命周期,开发者只需填写实现代码 (如 Spring 中的 JdbcTemplate,Servlet 中的 HttpServlet.service() 与 doGet()/doPost())。
    • 重构抽取公共代码: 当发现多个类中存在大量重复的代码逻辑、且执行步骤顺序高度一致时,可将公共部分抽离至父类模板中。
    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 设计模式-模板方法模式
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!