适配器模式
大约 2 分钟
🧩 适配器模式(Adapter Pattern)
一句话概括:
在 不修改原有代码 的前提下,
把一个不兼容的接口,转换成客户端期望的接口。
✨ 常见命名后缀
AdapterAdaptorConverterTranslator
看到这些名字,优先联想到:接口不匹配,而非功能增强。
一、它解决了什么问题?
🎯 典型业务场景
- 系统已经定义好了 稳定接口
- 引入了 旧系统 / 第三方类 / 历史代码
- 两者 方法名、参数、返回值不一致
- ❌ 无法修改原有实现
🧠 如果不用适配器会怎样?
| 做法 | 问题 |
|---|---|
| 到处写转换代码 | 重复、难维护 |
| 直接改旧代码 | 风险高、不可控 |
| 客户端适配所有差异 | 代码污染严重 |
👉 适配器模式:
- 封装差异
- 隔离变化
- 客户端只面对统一接口
二、核心思想(一定要记住)
适配器 = 实现目标接口 + 持有被适配对象
关键点
客户端只认 Target 接口
适配器内部负责:
- 方法映射
- 参数转换
- 结果包装
三、经典结构图
Client
↓
Target(目标接口)
↑
Adapter(适配器) ─────→ Adaptee(被适配类)📌 适配器的存在,是为了让双方都不用改。
四、三个核心角色
| 角色 | 职责 |
|---|---|
| Target | 客户端期望的接口 |
| Adaptee | 已存在但不兼容的类 |
| Adapter | 转换接口,桥接双方 |
五、最小 Java 示例
1️⃣ 目标接口(新系统标准)
public interface Charger {
void charge();
}2️⃣ 被适配类(老接口)
public class OldPowerOutlet {
public void providePower() {
System.out.println("provide power");
}
}3️⃣ 适配器
public class PowerAdapter implements Charger {
private OldPowerOutlet outlet;
public PowerAdapter(OldPowerOutlet outlet) {
this.outlet = outlet;
}
@Override
public void charge() {
outlet.providePower();
}
}4️⃣ 客户端使用
Charger charger = new PowerAdapter(new OldPowerOutlet());
charger.charge();✅ 客户端 完全不知道 OldPowerOutlet 的存在。
六、两种常见适配方式
🧱 1. 对象适配器(推荐)
- 使用 组合
- 更灵活
- 符合组合优于继承
Adapter has-a Adaptee🧬 2. 类适配器(不常用)
- 使用 继承
- 依赖多继承(Java 不支持)
Adapter extends Adaptee📌 在 Java 中,几乎只用对象适配器。
七、实战练习:统一支付接口 💰
🎯 业务背景
系统统一定义支付接口:
pay(amount)但接入了多个第三方:
| 支付渠道 | 实际方法 |
|---|---|
| 支付宝 | aliPay(money) |
| 微信 | wxPay(price) |
| 银行 | transfer(cash) |
目标:
- 客户端 只调用 pay
- 不感知任何第三方差异
💡 设计提示
PayService→ Target- 第三方 SDK → Adaptee
- 各支付适配器 → Adapter
八、真实框架中的适配器
Spring MVC
HandlerAdapter
SLF4J
- 适配 Log4j / Logback
JDK
InputStreamReader(字节 → 字符)
🚀 适配器模式在“接口整合”场景中无处不在。
🧠 总结一句话
适配器模式 = 不改旧代码 + 不污染新系统 + 平滑对接差异接口
当你看到:
- 接口不兼容
- 又不能重构
👉 第一反应就是:适配器模式 🧩