1. 什么是适配器模式
适配器模式(Adapter Pattern)是 GoF 23种设计模式中结构型设计模式之一,其核心思想是将一个类的接口转换成客户端所期望的另一个接口 ,从而使原本由于接口不兼容而不能一起工作的类可以协同工作。 适配器模式就像现实中的电源适配器:比如你的笔记本是美标插头,但中国插座是国标,就需要一个“适配器”来转换插头形状,使设备能正常工作。
在软件中,适配器模式让不兼容的接口变得兼容。
2.为什么需要适配器模式
在软件开发中,经常遇到以下情况:
- 已有一个功能完善的类(如第三方库、遗留系统组件),但它的接口与当前系统要求的接口不一致。
- 不能或不希望修改原有类的代码(比如没有源码、修改成本高、违反开闭原则)。
- 需要复用已有组件,但又必须满足新的接口规范。
此时,直接使用会报错或逻辑不通。适配器模式提供了一种非侵入式的解决方案:通过新增一个“适配器”类来桥接新旧接口,实现无缝集成。
3. 角色与UML
classDiagram
class Client {
+main()
}
class Target {
<<interface>>
+request()
}
class Adapter {
-adaptee: Adaptee
+request()
}
class Adaptee {
+specificRequest()
}
Client --> Target : uses
Adapter ..|> Target : implements
Adapter --> Adaptee : delegates to
| 类 / 接口 | 模式中的角色 | 作用与职责 |
|---|---|---|
Target | 目标接口 | 定义客户端所期望的标准接口。客户端通过该接口调用服务,无需关心具体实现是原生类还是适配后的类。 |
Adaptee | 被适配者 | 已存在的、具有所需功能但接口与 Target 不兼容的类。通常来自第三方库、遗留系统或不可修改的组件。 |
Adapter | 适配器 | 实现 Target 接口,并内部持有 Adaptee 的实例(对象适配器)或继承 Adaptee(类适配器),负责将 Target 接口的方法调用转换为对 Adaptee 的调用,起到“接口翻译”作用。 |
Client | 客户端 | 使用 Target 接口的调用方。它只依赖于目标接口,对适配器和被适配者的存在完全透明,从而实现解耦。 |
4. Java代码示例
1、目标接口(Target):新手机期望的充电接口(USB-C)
interface USB_C_Charger {
void chargeWithUSB_C();
}
2、被适配者(Adaptee):老充电器(只有 Micro-USB)
class OldCharger {
public void chargeWithMicroUSB() {
System.out.println("🔋 使用 Micro-USB 充电中...");
}
}
3、适配器(Adapter):把 Micro-USB 转成 USB-C
class ChargerAdapter implements USB_C_Charger {
private OldCharger oldCharger; // 持有老充电器
public ChargerAdapter(OldCharger oldCharger) {
this.oldCharger = oldCharger;
}
@Override
public void chargeWithUSB_C() {
System.out.println("🔌 适配器:将 USB-C 请求转为 Micro-USB...");
oldCharger.chargeWithMicroUSB(); // 委托给老充电器
}
}
4、客户端(Client)
public class Client {
public static void main(String[] args) {
OldCharger oldCharger = new OldCharger(); // 老充电器
USB_C_Charger adapter = new ChargerAdapter(oldCharger); // 适配器包装
adapter.chargeWithUSB_C(); // 成功用老充电器给新手机充电!
}
}
运行结果
🔌 适配器:将 USB-C 请求转为 Micro-USB...
🔋 使用 Micro-USB 充电中...
5. 优缺点
优点:
- 提高复用性:无需修改现有类即可复用其功能。
- 解耦:客户端只依赖 Target 接口,与 Adaptee 解耦。
- 符合开闭原则:对扩展开放(加适配器),对修改关闭(不改 Adaptee)。
- 透明性好:客户端无需知道背后使用的是适配器还是原生实现。
缺点:
- 增加系统复杂度:每种不兼容都需要一个适配器,适配器过多会使代码难以维护。
- 类适配器受限:在 Java 等单继承语言中无法通过继承实现多适配。
6. 典型应用
- Spring MVC: 其中的
HandlerAdapter就是适配器模式的体现:它将不同类型的 Controller(如注解式、实现 Controller 接口等)适配为统一的处理流程。 - 日志框架整合:应用使用 SLF4J(Target),底层可能是 Log4j、Java Util Logging(Adaptee),SLF4J 提供了对应的适配器桥接。
一句话总结:适配器模式通过一个“转接头”类,将不兼容的接口转换成客户端期望的接口,让新旧系统或组件能够无缝协作。