钩子方法是子类安全干预主流程的核心手段,需置于关键岔路口、设计protected可修改变量、仅做轻量微调、配合明确命名与默认行为。

抽象类配合钩子方法,是让子类在不破坏主流程的前提下,安全、轻量地干预执行逻辑的核心手段。关键不在“能不能改”,而在“在哪改、怎么改才可控”。
钩子方法要放在流程的关键岔路口
模板方法中真正需要子类介入的位置,通常是条件判断前、操作前后、或资源释放点。比如:
- beforeXxx():用于预检查、参数调整、日志打点(如修改父类的logLevel变量)
- afterXxx():用于清理临时文件、关闭连接、更新统计计数器(如递增父类的retryCount)
- shouldXxx():返回 boolean,控制某段逻辑是否执行(如跳过体检步骤、绕过缓存校验)
父类变量需设计为 protected 且可被安全修改
钩子方法能干预流程,前提是它能访问并合理修改父类状态。例如:
- 把需要被子类影响的变量声明为 protected(如 protected boolean skipValidation = false;)
- 在钩子方法里直接赋值:skipValidation = true;,后续模板方法中
if (!skipValidation) validate();就自动生效 - 避免在钩子中修改 final 或不可变对象;若需配置集合,用 protected List
customHeaders = new ArrayList();
子类覆盖钩子时只做“小动作”,不接管主干
钩子不是重写整个步骤,而是微调。正确做法是:
- 在 beforeProcess() 中设置 timeoutMs = 5000;,而不是重新实现网络请求
- 在 shouldRetry() 中根据 HTTP 状态码返回 true/false,而不是自己写重试循环
- 不抛异常、不阻塞线程、不改变模板方法已定义的执行顺序
结合默认行为 + 明确命名,降低误用风险
一个没文档、没默认值、命名模糊的钩子,等于埋雷。实战建议:
- 布尔钩子一律以 isXxxEnabled() 或 shouldXxx() 命名,返回值有符合直觉的默认(如 return true; 表示“默认开启”)
- 空实现钩子必须是 protected void xxx() {},不能抛 NPE 或静默失败
- Javadoc 写清楚:“子类可重写此方法,在数据转换前修改 inputMap 的键名格式”










