抽象类专注“身份归属”(is-a关系),限深两层、单一职责;接口承载“能力组合”,用default方法提供可插拔行为;正交能力通过组合而非继承实现。

Java 中接口与抽象类协同使用,是化解多层继承复杂性的核心手段:抽象类聚焦“身份归属”,接口承载“能力组合”,二者分工明确,避免把“是什么”和“能做什么”混在同一继承链里。
用抽象类锚定本质层级,严格限制深度
抽象类应只表达不可替代的 is-a 关系,比如 Animal → Mammal 合理,Mammal → Carnivore → Lion 就越界。超过两层后,中间类往往只是分类标签或配置变体,而非真正需要复用状态与骨架逻辑的抽象维度。
- 团队可约定:具体类必须声明为 final,禁止被继承
- 用 IDE 或 SonarQube 检查 “Inheritance depth”,超两层自动标黄预警
- 若某抽象类只有一个子类,直接移除抽象修饰,转为普通类或接口实现
把正交能力全交给接口,不塞进继承树
导出、筛选、定时刷新、加解密、重试、日志——这些不是“身份”,而是可插拔的能力。放在继承链中只会让结构膨胀、修改牵一发而动全身。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 定义 Exportable、Schedulable、Retryable 等接口,用 default 方法提供基础实现(如
exportToExcel()) - 具体类按需 implements,不强制统一父类;避免为了“归类”硬造一个
BaseReport - 接口不带字段,不维护状态,只描述契约和轻量行为
共性逻辑下沉为单一层级抽象类,不跨维度混搭
远程调用的重试、熔断、TraceId 注入可以共用,但不应和权限校验、缓存策略、日志格式混在同一个抽象基类里。每个抽象类只解决一个稳定问题。
立即学习“Java免费学习笔记(深入)”;
- 抽象类命名体现单一职责,例如 AbstractRemoteService、AbstractEventPublisher
- 子类数量控制在 2–5 个;超出说明粒度太粗,该拆分而不是加深
- 构造器保持简洁,可配置项通过 protected final 字段 或 builder 注入,不执行复杂初始化
用组合接管易变逻辑,替代继承式“打补丁”
当出现 CachedService、ValidatedService 这类中间层时,大概率是设计信号:它不是一种新“类”,而是对能力的装配。这类逻辑不该靠继承传递,而应通过字段持有并委托调用。
- 将校验逻辑抽成 ValidationRule 策略对象,构造时传入
- 把日志能力转为 Loggable 接口 + DefaultLogger 实现,业务类持有一个
private final Loggable logger - 模板方法中统一调度:
if (revoker != null) revoker.revoke();,灵活开关行为

















