Appearance
适配器模式(Adapter Pattern)
1. 官方定义
"Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)
核心:将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。
2. 模式解释
核心思想
- 接口转换:通过中间层(适配器)解决新旧系统或第三方组件的接口不兼容问题。
- 透明集成:客户端仅依赖目标接口,无需感知适配器背后的复杂转换逻辑。
典型结构
plaintext
Client → |<<Interface>>|
Target
△
|
┌────────┴────────┐
| |
ObjectAdapter ClassAdapter
(持有Adaptee实例) (继承Adaptee)
| |
▼ ▼
Adaptee Adaptee
优点
- 复用性:集成不兼容的现有类或第三方库。
- 解耦性:客户端代码与具体实现解耦,仅依赖目标接口。
- 灵活性:支持多个适配器处理不同接口变体(如不同版本的 API)。
缺点
- 过度适配风险:滥用可能导致系统复杂度增加(如嵌套多层适配器)。
- 性能损耗:适配器转发调用可能引入额外开销(如网络请求代理)。
3. 解决的问题
经典场景
- 第三方库集成
- 旧系统调用新支付接口(如支付宝接口适配银行遗留系统)。
- 接口版本升级
- 新版 API 兼容旧版客户端(如
V2APIAdapter
包装V3API
)。
- 新版 API 兼容旧版客户端(如
- 跨平台兼容
- 统一不同数据格式(如 XML 转 JSON 适配器)。
4. 实现注意事项
关键实现点
- 适配器类型选择
- 类适配器:通过多重继承实现(Java 不支持,C++ 适用),直接继承被适配类。
- 对象适配器:通过组合持有被适配对象实例(推荐方式,更灵活)。
- 接口匹配粒度
- 适配器可能需聚合多个被适配类的方法(如合并
LegacyDB.read()
和NewDB.query()
)。
- 适配器可能需聚合多个被适配类的方法(如合并
- 异常处理
- 转换过程中需处理接口差异导致的异常(如字段缺失、类型不匹配)。
代码示例(对象适配器)
java
// 目标接口(客户端期望的接口)
interface ModernPrinter {
void print(String text);
}
// 被适配类(已有但不兼容的类)
class LegacyPrinter {
void printDocument(String content, int copies) {
for (int i=0; i<copies; i++) {
System.out.println(content);
}
}
}
// 对象适配器
class PrinterAdapter implements ModernPrinter {
private LegacyPrinter legacyPrinter;
public PrinterAdapter(LegacyPrinter printer) {
this.legacyPrinter = printer;
}
@Override
public void print(String text) {
legacyPrinter.printDocument(text, 1); // 固定 copies=1
}
}
// 客户端调用
ModernPrinter printer = new PrinterAdapter(new LegacyPrinter());
printer.print("Hello Adapter!");
5. 实现变体
类型 | 特点 | 适用场景 |
---|---|---|
对象适配器 | 通过组合持有被适配对象(推荐) | 需适配多个类或子类 |
类适配器 | 通过继承被适配类(需语言支持多重继承) | 简单适配且无需运行时动态切换 |
双向适配器 | 同时实现两个接口,支持双向转换 | 新旧系统需互相调用 |
6. 相似模式对比
模式 | 核心区别 |
---|---|
桥接模式 | 分离抽象与实现,适配器模式解决已有接口不兼容问题 |
装饰者模式 | 增强对象功能,适配器模式改变对象接口 |
外观模式 | 简化复杂子系统接口,适配器模式解决接口不匹配 |
7. 组合使用场景
常见搭配模式
- 工厂模式
- 场景:由工厂类决定生成哪种适配器(如根据配置选择 XML/JSON 适配器)。
- 装饰者模式
- 场景:在适配过程中添加额外功能(如日志记录、缓存)。
- 代理模式
- 场景:远程调用时适配不同协议(如 REST 到 gRPC 的适配代理)。
8. 总结与关键词
关键词
- 适配器模式 (Adapter Pattern)
- 设计模式 (Design Patterns)
- 接口转换 (Interface Conversion)
- 对象适配器 (Object Adapter)
- 类适配器 (Class Adapter)
- 第三方集成 (Third-Party Integration)
总结
- 核心价值:通过中间层解决接口不兼容问题,实现系统间无缝协作。
- 适用场景:集成遗留代码、第三方库或处理多版本接口兼容。
- 实现选择:优先使用对象适配器(组合优于继承),慎用多重继承。
- 经典案例:
- Java 的
InputStreamReader
(适配InputStream
到Reader
)。 - Spring 的
HandlerInterceptorAdapter
(简化拦截器实现)。
- Java 的
附:适配器模式 vs 外观模式
模式 | 目标 | 复杂度 |
---|---|---|
适配器 | 接口转换(一对一映射) | 通常较简单 |
外观 | 简化接口(聚合多个子系统) | 可能较复杂 |
通过合理使用适配器模式,可显著降低系统重构成本,提升组件复用性,是应对接口差异的核心设计工具。