接口是实现依赖倒置原则最自然的工具,它定义行为契约、隔离高层与低层模块、明确职责边界、声明依赖类型、支持构造注入,并优先于抽象类作为依赖契约载体。

接口是实现依赖倒置原则(DIP)最自然、最常用的工具。它不提供实现,只定义行为契约,让高层模块与低层模块都面向它编程,从而切断具体类之间的硬依赖,支撑高内聚、低耦合的设计目标。
用接口明确职责边界,聚焦单一行为
每个接口应只描述一类可替换的能力,比如 PaymentProcessor、UserRepository 或 NotificationSender。接口名要体现意图,方法名要表达动作,避免“万能接口”或包含无关操作。
- ✅ 好:接口
Logger只含info()、error();CacheService只含get()、put() - ❌ 不好:一个
SystemService接口同时定义日志、缓存、配置加载——职责混杂,违背单一职责,也削弱了可替换性
让所有依赖都声明为接口类型
在类中声明字段、方法参数、返回值时,统一使用接口而非具体实现类。这从编码层面强制解耦。
- 构造函数里接收
UserService userService,而不是DatabaseUserServiceImpl - 方法签名写
public void process(Order order, PaymentProcessor processor),而非AlipayProcessor - 返回类型用
List<user></user>或自定义接口如UserQueryResult,而非ArrayList<user></user>或JdbcUserQueryResult
通过构造注入把实现交给外部,不自己创建
类内部不出现 new XxxImpl(),也不调用静态工厂。依赖由外部(测试代码、Spring容器、手动组装)注入,确保该类只关心“做什么”,不关心“怎么做”。
立即学习“Java免费学习笔记(深入)”;
- 典型写法:
public class OrderService { private final NotificationSender notifier; public OrderService(NotificationSender notifier) { this.notifier = notifier; } } - 这样,
OrderService的逻辑完全独立于通知渠道;换短信、邮件或站内信,只需传入不同实现,类本身无需修改 - 单元测试时可轻松传入
MockNotificationSender,验证业务流程是否触发了正确通知
配合抽象类做有限共享,但优先选接口
当多个实现需要共用部分逻辑(如日志前缀、重试封装),可用抽象类继承接口;但抽象类仍应面向接口设计,且不能替代接口作为依赖声明的目标。
- 例如:接口
HttpClient定义get()、post();抽象类BaseHttpClient提供默认超时设置和请求头组装 - 但
ApiService的字段仍声明为private final HttpClient client,不是BaseHttpClient - 抽象类用于减少重复,接口才是依赖契约的载体


















