接口定义能力契约与解耦边界,抽象类封装通用流程与共享骨架,二者协同实现“能做什么”与“怎么做得标准”的分层设计。

接口和抽象类在框架设计中不是互斥选项,而是分工明确的协作工具。关键不在于“哪个更好”,而在于“谁该管什么”。
接口负责定义能力契约与解耦边界
框架对外暴露的能力、插件接入点、回调约定,几乎都靠接口完成:
-
扩展点声明:Spring 的
BeanPostProcessor、MyBatis 的Interceptor都是接口。框架不关心你如何实现,只约定“你必须提供 before() 和 after() 方法”——这正是接口的契约本质。 -
多能力叠加:一个自定义组件可以同时实现
InitializingBean(初始化)、DisposableBean(销毁)、Ordered(排序)三个接口,无需改变继承结构,也不引入无关逻辑。 -
面向接口编程:框架内部大量使用接口类型变量(如
ResourceLoader loader),具体实现由配置或自动装配决定。替换底层实现(如从ClassPathResource换成UrlResource)完全不影响调用方代码。
抽象类负责封装通用流程与共享骨架
当框架内部存在固定步骤+可变细节的模式时,抽象类就是天然选择:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
模板方法模式:Spring 的
JdbcDaoSupport、WebMvc 的AbstractController都是典型。它们把“获取连接→执行SQL→关闭资源”或“解析请求→调用处理器→渲染视图”的流程固化,只留doExecute()或handleRequestInternal()交给子类定制。 -
减少重复样板代码:比如日志框架中的
AbstractLogger可预置线程上下文绑定、MDC 清理、异步刷盘等逻辑,子类只需关注“怎么格式化消息”和“往哪写”。避免每个 Logger 实现都重写同一套基础设施。 -
强制初始化约束:抽象类可定义带参构造器(如
public AbstractDataSource(String url)),确保子类在创建时就必须传入必要依赖,比接口 + 工厂方式更直接可控。
二者协同:接口定义“能做什么”,抽象类实现“怎么做得标准”
真实框架里常组合使用:
立即学习“Java免费学习笔记(深入)”;
- 先定义
TaskExecutor接口,声明execute(Runnable task)行为; - 再提供
AbstractExecutorService抽象类,封装线程池管理、拒绝策略、生命周期钩子等共性; - 最后由
ThreadPoolTaskExecutor等具体类继承抽象类并实现接口——既满足多态调用,又复用核心逻辑。
这种分层让框架使用者既能按需实现轻量接口,也能快速继承成熟骨架,还保留了替换底层实现的自由度。

















