接口是行为契约而非模板,用于解耦可变实现(如短信、数据库、缓存更换),通过依赖注入倒置依赖方向,倡导窄接口(方法≤3个、参数≤2个)以保障单一职责与可测试性。

接口不是模板,而是行为契约
接口不是为了多写几行代码,也不是为了让类看起来更“规范”。它的存在意义很实在:当某段逻辑未来可能换实现——比如短信从阿里云切到腾讯云、数据库从 MySQL 换成 PostgreSQL、缓存从本地 Map 改为 Redis——那就该把它抽成接口。调用方只认这个契约,不关心背后是谁在干活。
解耦的关键在于依赖方向倒过来
传统写法容易把高层模块和低层实现绑死:
-
错误示范:
new AlipayGateway()出现在订单服务里,等于把支付方式写死了 -
正确做法:声明
private final PaymentGateway gateway,具体实现由外部注入(如 Spring 的@Autowired或构造函数传入)
这样改支付渠道时,只需新增一个 WechatPaymentGateway 类,订单服务代码一行不动。
窄接口比大而全的接口更可靠
一个接口如果塞进太多方法,比如同时包含发送、重试、日志、状态查询,那它就不再是单一职责的契约,而是多个角色的混合体。结果往往是:
- 新加一种消息通道,却被迫重写日志格式或重试策略
- 测试时 mock 不干净,因为方法之间隐式依赖内部状态
- 接口方法超过 3 个、单个方法参数超过 2 个,就该考虑拆分
例如把 MessageSender 和 RetryPolicy 分开定义,运行时通过组合使用,而不是让一个类扛下所有责任。
可测试性是接口设计最直接的回报
没有接口,单元测试只能走真实链路:发一次真短信、连一次真数据库——慢、不稳定、还可能污染环境。有了接口,就能轻松 mock:
- 用
Mockito.mock(MessageSender.class)替代真实发送器 - 设定特定返回值或异常,验证业务逻辑是否按预期处理失败场景
- 一旦 mock 后行为异常(比如空指针),往往说明接口方法悄悄依赖了未注入的字段,这是设计漏洞的信号
接口让测试真正成为“单元”级,而不是“集成”级。










