← 返回题目列表

模板方法模式和回调机制有什么关系?

高频 中等 第 6 / 26 题 更新于 2026/08/02
模板方法模式回调JdbcTemplate框架设计

简化版

模板方法模式通过继承让父类固定流程、子类重写步骤;回调机制通过组合或函数参数把可变步骤传进去,让框架固定流程、调用回调完成变化。两者思想相近,都是“固定骨架 + 留扩展点”,区别在于扩展方式:模板方法偏继承,回调偏组合。Spring 的 JdbcTemplate 更像模板 + 回调的工程化变体。

详细版

模板方法写法:

abstract class DataProcessor {
    public final void process() {
        open();
        doProcess();
        close();
    }

    protected abstract void doProcess();
}

回调写法:

template.execute(connection -> {
    // 使用连接执行业务
});

两者都由模板控制公共流程:打开资源、执行变化逻辑、关闭资源。不同点是模板方法让子类覆盖 doProcess,回调让调用方传入函数或对象。

记忆钩子:模板方法是“子类填空”,回调是“把填空题作为参数传进去”。

完整版教学

面试提示:模板方法和回调的区别要围绕“继承扩展”与“组合注入”讲,顺手补一句测试和灵活性差异会更完整。

一、两者共同点是固定流程和开放扩展点

不管是模板方法还是回调,都有这个结构:

固定步骤 A
可变步骤 B
固定步骤 C

差异只在可变步骤从哪里来。模板方法从子类来,回调从参数或组合对象来。

二、模板方法依赖继承

模板方法中,父类这样写:

public final void execute() {
    before();
    doExecute();
    after();
}

protected abstract void doExecute();

子类提供变化部分:

class ExportJob extends AbstractJob {
    protected void doExecute() {
        exportFile();
    }
}

优点是结构清晰,适合同一类对象形成稳定继承层次。

三、回调依赖组合或函数参数

回调方式:

class ExecuteTemplate {
    public void execute(Callback callback) {
        before();
        callback.call();
        after();
    }
}

调用方传入变化逻辑,不需要继承:

template.execute(() -> exportFile());

优点是更灵活,避免继承层次膨胀。

四、JdbcTemplate 是典型模板加回调

Spring JdbcTemplate 固定流程:

获取连接 -> 创建 Statement -> 执行 SQL -> 映射结果 -> 释放资源

开发者传入 SQL、参数和 RowMapper:

jdbcTemplate.query(sql, (rs, rowNum) -> mapUser(rs));

框架负责资源和异常转换,回调负责结果映射。这体现了模板思想,但不是传统继承式模板方法。

五、什么时候选继承式模板

适合继承式模板:

场景原因
子类是一类稳定类型继承层次清楚
流程和扩展点长期稳定父类契约稳定
子类需要多个相关步骤继承能组织多方法
框架生命周期父类统一调度

例如 AbstractImportJobBaseController 某些受控场景。

六、什么时候选回调

适合回调:

  • 只需要传入一个或少数变化点;
  • 不想创建大量子类;
  • 变化逻辑轻量;
  • 希望运行时灵活组合;
  • 需要函数式写法。

例如数据库操作、重试模板、锁模板、事务模板。

七、继承和回调可以结合

父类模板内部也可以使用回调,回调模板也可以被子类封装。不要把两者看成互斥关系。

关键是:公共流程谁控制?变化点如何注入?继承是否值得?

八、常见误区与追问

  • 误区:模板方法只能通过继承实现。 GoF 模板方法偏继承,但工程中常用回调实现同样思想。
  • 误区:回调和模板方法完全无关。 两者都体现固定骨架和扩展点。
  • 误区:JdbcTemplate 就是纯 GoF 模板方法。 它更准确地说是模板思想加回调机制。
  • 误区:能用继承就不用回调。 简单变化点用回调通常更轻、更灵活。
  • 追问:回调相比继承有什么优势? 减少子类数量,运行时灵活传入行为,更符合组合优先。
  • 追问:继承式模板有什么优势? 多步骤扩展、稳定家族类型和框架生命周期更清晰。
  • 追问:如何判断选哪个? 看变化点数量、继承层次是否自然、是否需要运行时组合。

九、加强记忆

  1. 两者共同点是固定骨架和开放扩展点。
  2. 模板方法靠继承,回调靠组合或函数参数。
  3. JdbcTemplate 是模板思想加回调的经典例子。
  4. 多步骤稳定家族适合继承式模板。
  5. 单点轻量变化适合回调。
  6. 两者可结合,不必二选一。