抽象类与接口是互补协作的架构工具:抽象类定义骨架与共性流程,接口声明能力与协作契约;二者结合可兼顾复用性、扩展性与解耦性。

抽象类和接口不是非此即彼的选择,而是互补协作的架构工具。在大型企业系统中,抽象类负责定义“骨架”与“共性流程”,接口负责声明“能力”与“协作契约”,二者结合才能兼顾复用性、扩展性与解耦性。
用抽象类统一核心流程与公共状态
当多个模块共享相同的执行结构、初始化逻辑或内部状态时,抽象类是不可替代的载体:
- 定义带构造方法的基类(如 AbstractOrderProcessor),封装通用幂等校验、日志埋点、事务模板和基础字段(
orderId、createdAt) - 声明抽象方法(如
validate()、executeInternal()),强制子类实现业务差异化逻辑,但保证调用时机和上下文一致 - 提供
protected工具方法(如notifyAfterSuccess()),供子类按需调用,避免重复编码
用接口暴露横切能力与协作协议
接口解决单继承限制,并支持能力组合与服务发现,是微服务间松耦合的关键:
- 为不同维度的能力定义独立接口:如 AsyncCapable(声明
asyncExecute())、Compensable(声明compensate())、Traced(声明startTraceSpan()) - 具体服务类可同时
extends AbstractOrderProcessor并implements AsyncCapable, Compensable,实现“主干复用 + 能力插拔” - 网关或编排层通过
if (obj instanceof AsyncCapable)或 Spring 的@Qualifier动态识别并调用对应能力,无需修改主流程
用抽象类 + 接口组合构建可演进的领域模型
在DDD或分层架构中,二者协同建模语义与行为:
立即学习“Java免费学习笔记(深入)”;
- 定义领域抽象基类(如 AggregateRoot
),含 apply(Event)、getUncommittedEvents()等模板方法,管理聚合生命周期 - 为跨聚合能力定义接口(如 EventPublisher、Repository
),由基础设施层实现,业务层只依赖接口 - 聚合子类(如 Order)继承
AggregateRoot<order></order>,同时被OrderRepository持有——抽象类管“内在一致性”,接口管“外在协作”
避免常见误用,守住设计边界
二者混用的前提是职责清晰,否则反而增加理解成本:
- 不在接口中定义
default方法来维护状态(如计数器、缓存),这违背接口无状态契约;状态应归属抽象类或具体实现 - 不为“能做什么”建抽象类(如把
Flyable设计成抽象类),也不为“是什么”建接口(如用Car接口代替AbstractVehicle) - 当一个类型既需要继承又需多能力时,优先选“单抽象类 + 多接口”,而非试图用接口模拟类层次


















