抽象类通过钩子方法实现“主干不变、局部可插拔”,父类定骨架锁流程,子类仅在关键岔路口(如beforeXxx、afterXxx、shouldXxx)做轻量微调;钩子需访问protected可变状态,命名清晰、默认合理、文档完备。

抽象类在框架设计中用钩子方法让子类控制执行流程,核心是把“主干不变”和“局部可插拔”分开——父类定骨架、锁流程,子类只在明确预留的轻量节点上做微调。
钩子方法要放在流程的关键岔路口
不是所有地方都适合加钩子,得选真正影响分支走向或状态变更的位置。比如:
-
beforeXxx():常用于参数预处理、日志打点、开关校验(如修改父类的
isDebugMode) -
afterXxx():适合资源释放、统计更新、结果归档(如递增
successCount) - shouldXxx():返回 boolean,直接决定某段逻辑是否执行(如跳过缓存、绕过权限检查)
父类变量需声明为 protected 且支持安全修改
钩子能起作用,前提是它能读写父类状态。注意三点:
- 需要被子类干预的字段,必须是
protected,不能是private或final - 推荐用可变对象,比如
protected List<String> customHeaders = new ArrayList<>(); - 避免在钩子里改不可变对象(如 String、LocalDateTime),否则修改无效
子类覆盖钩子只做小动作,不接管主干
钩子不是重写整个步骤,而是“拧一颗螺丝”,不是换整台发动机:
立即学习“Java免费学习笔记(深入)”;
- 在
beforeProcess()中设timeoutMs = 8000;,而不是自己发 HTTP 请求 - 在
shouldRetry()中根据响应码返回true/false,而不是手写重试循环 - 不抛异常、不阻塞线程、不改变模板方法已定义的顺序
命名清晰 + 默认行为合理 + 文档说明到位
一个好钩子,光能用还不够,得让人一眼看懂怎么用:
- 布尔钩子统一用
shouldXxx()或isXxxEnabled()命名,返回值符合直觉(如默认return true;表示开启) - 空实现钩子必须是
protected void xxx() { },不能抛 NPE 或静默失败 - Javadoc 明确写清用途,例如:“子类可重写此方法,在序列化前修改字段命名策略”
不复杂但容易忽略。关键不在能不能改,而在改得清楚、改得安全、改得可控。


















