钩子方法是模板方法模式中可选的扩展点,声明为protected,含空实现、布尔返回或默认行为,置于流程边界处,与抽象方法协同实现柔性定制。

钩子方法是模板方法模式中用于扩展子类行为的可选方法,它在抽象父类中声明默认空实现或默认逻辑,子类按需重写。设计的关键在于“提供扩展点但不强制实现”,让子类决定是否介入流程。
钩子方法的声明方式
在抽象模板类中,用 protected 修饰、返回 void 或布尔值(便于控制流程分支),方法体为空或含安全默认逻辑:
- 空实现钩子:适合纯扩展场景,如
protected void onBeforeProcess() { } - 布尔钩子:常用于条件拦截,如
protected boolean shouldSkipValidation() { return false; },模板方法中据此跳过某步骤 - 带默认行为的钩子:如
protected void logStep(String step) { System.out.println("[INFO] " + step); },子类可覆盖为 SLF4J 或异步日志
钩子方法的放置位置
钩子应插在模板方法的关键决策点或边界处,而非核心算法内部:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 流程开始前(如参数校验后、主逻辑前):用于预处理或权限检查
- 步骤切换时(如“读取数据”和“转换数据”之间):便于插入中间处理或埋点
- 异常处理前后:如
onError(Exception e)和onSuccess(),统一监控但不干扰主干 - 避免放在循环体内或高频调用路径上,防止子类重写引入性能隐患
与抽象方法的区别与配合
钩子方法不是强制实现的“骨架缺口”,而是可选的“柔性插槽”。它常与抽象方法协同使用:
立即学习“Java免费学习笔记(深入)”;
- 抽象方法定义必须实现的核心行为(如
doExecute()) - 钩子方法补充非必需的辅助行为(如
onStart(),onFinish()) - 一个典型组合:
templateMethod()调用prepare()(钩子)、doWork()(抽象)、cleanup()(钩子),子类只关心doWork(),其余可忽略
实际设计建议
保持钩子轻量、语义明确、副作用可控:
- 方法名体现意图,如
isRetryEnabled()比hook1()更易理解 - 避免在钩子中修改模板方法依赖的状态变量,除非文档明确说明
- 若钩子逻辑较重(如网络调用),考虑加超时或降级,默认实现应保障主流程不受影响
- 必要时提供注释说明触发时机和推荐用途,例如:
// called after result is computed, before returning — use for metrics only

















