适配器模式
适配器模式用于把一个已有接口转换成客户端期望的接口,让原本不兼容的类可以一起工作。
一句话理解:接口不合适,但功能能用,就加一层适配器。
解决什么问题
常见情况:
- 老系统接口不能改,但新代码希望使用统一接口。
- 第三方 SDK 的方法名、参数结构和项目规范不一致。
- 多个渠道能力类似,但调用方式不同。
如果业务代码直接兼容各种旧接口,会变成大量特殊判断。适配器把这些差异封装起来,让业务层只面对统一接口。
基本结构
text
Client -> Target
^
|
Adapter -> Adaptee角色:
Target:业务希望使用的目标接口。Adaptee:已有类或第三方接口。Adapter:把Adaptee转换成Target。
Java 示例
老短信 SDK:
java
class LegacySmsApi {
public boolean sendText(String mobile, String content) {
System.out.println("legacy sms send");
return true;
}
}业务统一接口:
java
interface SmsClient {
void send(String phone, String message);
}适配器:
java
class LegacySmsAdapter implements SmsClient {
private final LegacySmsApi legacySmsApi;
LegacySmsAdapter(LegacySmsApi legacySmsApi) {
this.legacySmsApi = legacySmsApi;
}
public void send(String phone, String message) {
boolean success = legacySmsApi.sendText(phone, message);
if (!success) {
throw new RuntimeException("send sms failed");
}
}
}业务层:
java
SmsClient smsClient = new LegacySmsAdapter(new LegacySmsApi());
smsClient.send("13800000000", "login code: 123456");业务层不需要知道老 SDK 的方法名是 sendText,也不需要处理它返回 boolean 的细节。
对象适配器和类适配器
对象适配器
通过组合持有被适配对象:
java
class Adapter implements Target {
private final Adaptee adaptee;
}这是 Java 中更常用的方式,灵活、可替换、可测试。
类适配器
通过继承被适配类,同时实现目标接口。
Java 单继承限制较多,因此实际项目中不常用。
使用场景
- 包装第三方 SDK。
- 兼容老接口。
- 多渠道接口统一,例如短信、支付、物流。
- Controller 入参和内部 Command 对象转换。
- 把外部系统返回结构适配成本系统模型。
优点
- 复用旧代码,不需要修改原类。
- 让业务层面对统一接口。
- 把兼容逻辑集中在适配器中。
缺点
- 适配层过多会增加理解成本。
- 如果目标接口设计不合理,适配器会越来越臃肿。
- 只能解决接口不兼容,不能解决底层能力缺失。
和其他模式的区别
| 模式 | 重点 |
|---|---|
| 适配器 | 解决接口不兼容 |
| 外观 | 简化一组复杂接口 |
| 装饰器 | 不改接口,增强功能 |
| 代理 | 控制访问或增加访问过程能力 |
实战注意
适配器适合放在基础设施层或防腐层中。不要让外部系统的模型、异常、字段名直接污染核心业务代码。