控制继承深度在两层以内最有效,超三层易致职责模糊、维护成本上升;应禁用深层继承,改用组合+接口,并将抽象类转为final、方法设为final,仅保留受控hook。

控制继承深度在两层以内是最直接有效的办法。超过三层,类之间的职责就容易模糊,改一处可能牵动整个链,理解、测试和重构成本都会明显上升。
硬性限制继承层级
明确约定:Animal → Dog 是第一层,Dog → ServiceDog 是第二层,到此为止。再往下如 ServiceDog → CertifiedServiceDog,不应继续继承——这种差异通常是角色、配置或策略变化,不是本质类型升级。
- 团队代码规范中写明:“所有具体实现类必须声明为 final”,禁止被继承
- 用 SonarQube 或 IDEA 的 “Inheritance depth” 检查,在编码时标黄提示超深类(如超过2层)
- 已有深层链(如 Vehicle → Car → Sedan → ElectricSedan)先识别中间层是否只是分类标签,而非承载真正复用逻辑
用组合 + 接口替代中间层
当某个抽象类(如 CachedService、ValidatedService)只是给多个子类“打补丁”,它实际是能力装配者,不是语义上的“是一种”。这类层最容易引发复杂度爆炸。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 把功能拆成接口,例如 Cacheable、Loggable、RetryPolicy,提供默认实现但不带状态
- 原继承结构中删掉 extends,改为持有一个接口字段(如 private final Cacheable cache;),构造器注入
- 让具体类实现顶层业务接口(如 Dao),而不是继承抽象基类,保持类型兼容又解耦
基类只保留不可变契约
父类不该塞进可变行为。它只定义稳定不变的语义(如“能启动”“能停止”),而把策略、配置、扩展点显式暴露出来。
- 方法尽量声明为 final,只留少数受控 hook(如 protected abstract doProcess())
- 所有可变参数(超时、序列化格式、日志级别)必须通过构造函数或 Builder 注入,不设默认值字段
- 避免在父类构造器中调用可被重写的方法;字段全设为 private,需扩展时提供受控的 protected 方法
定期识别重构信号
不用等出问题才行动。日常开发中留意这些信号,及时扁平化:
- 某抽象类只有唯一子类 → 很可能过度设计,考虑移除或转为具体类
- 子类大量重写父类方法只为“绕过逻辑” → 那部分逻辑本该抽成可插拔组件
- 多个子类仅字段不同、行为雷同 → 说明建模维度错位,应改用配置 + 组合
- “查找所有子类”结果里,多个子类共享的只是几个工具方法 → 抽成工具类或默认方法接口更合适
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










