适配器模式(Adapter Pattern)
意图
包装(封装)一个已有的类,使其匹配新的接口,从而让旧代码适应新的需求,而不需要修改原始代码。
主要解决
• 旧系统(或第三方库)的接口与新系统不兼容,导致不能直接使用。
• 需要在不修改旧代码的情况下,让其适应新接口,保证兼容性。
何时使用
1. 新旧系统接口不兼容,但必须一起工作(如老旧 API 适配新架构)。
2. 希望复用已有类,但接口不匹配(如不同数据库驱动、网络协议)。
3. 第三方库接口与应用接口不一致,但又无法修改第三方库代码。
结构
适配器模式通常包含以下角色:
1. Target(目标接口):定义新系统期望的接口。
2. Adaptee(被适配者):已有的老接口,需要被适配。
3. Adapter(适配器):将 Adaptee 转换为 Target,让它们能兼容工作。
类图
示例代码(Java 实现)
// 目标接口(新接口)
interface Target {
void request();
}
// 被适配者(老接口)
class Adaptee {
public void specificRequest() {
System.out.println("调用 Adaptee 的 specificRequest 方法");
}
}
// 适配器(Adapter)
class Adapter implements Target {
private Adaptee adaptee; // 持有 Adaptee 引用
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 适配器将 Target 的 request() 转换为 Adaptee 的 specificRequest()
System.out.println("适配器转换接口...");
adaptee.specificRequest();
}
}
// 测试
public class AdapterPatternDemo {
public static void main(String[] args) {
Adaptee oldSystem = new Adaptee();
Target adapter = new Adapter(oldSystem);
// 通过适配器调用老接口
adapter.request();
}
}
输出结果
适配器转换接口...
调用 Adaptee 的 specificRequest 方法
适配器模式的实现方式
1. 类适配器(基于继承)
• 适配器继承 Adaptee,实现 Target 接口。
• 优点:可以直接访问 Adaptee 的方法。
• 缺点:Java 不支持多继承,如果 Adaptee 已继承其他类,会导致适配器模式受限。
2. 对象适配器(基于组合)(推荐)
• 适配器持有 Adaptee 实例,通过组合方式调用其方法。
• 优点:更灵活,适配器可以适配多个 Adaptee,并且可以与继承无关。
优缺点
✅ 优点
• 兼容旧代码,避免直接修改 Adaptee,降低维护成本。
• 符合开闭原则,新需求可以通过适配器扩展,不影响原系统。
• 支持多种适配方式(类适配器、对象适配器)。
❌ 缺点
• 增加了额外的类,可能导致系统复杂度提高。
• 效率略低,特别是在对象适配器模式下,因为多了一层转发。
应用场景
|
场景 |
示例 |
|---|---|
|
旧 API 适配新接口 |
Java 中 InputStreamReader 适配 InputStream |
|
数据库适配 |
JDBC 适配不同数据库驱动 |
|
前端适配 |
Vue/React 适配老接口 |
|
电源适配器 |
220V 转换为 5V USB 充电 |
|
Android 适配 |
适配不同分辨率的 UI 组件 |
变体与扩展
• 双向适配器:同时适配新旧接口,使其可以双向兼容。
• 缺省适配器(默认适配器):提供默认实现,子类只需重写所需方法(如 Java WindowAdapter)。
• 接口适配器:用于接口中有多个方法,但子类只需要实现其中一个或部分方法(如 Java MouseAdapter)。
总结
1. 适配器模式的核心思想是“包装旧接口,使其适应新接口”,实现接口转换,让不兼容的类可以协同工作。
2. 适用于旧系统升级、接口不匹配的情况,如数据库驱动适配、API 兼容等场景。
3. 推荐使用对象适配器模式(基于组合),比类适配器模式(基于继承)更灵活。
4. 可能增加系统复杂性,但能降低代码改动成本,符合开闭原则。
你觉得这个解释清晰吗?是否需要进一步优化代码或提供其他语言示例?😊
浙公网安备 33010602011771号