适配器模式(Adapter Pattern),将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
它的核心思想是不修改现有代码,通过引入一个中间“适配器”角色,充当接口之间的“翻译官”或“转换头”,解决不同组件之间的兼容性问题。
优缺点
优点
- 优秀的复用性与兼容性: 无需修改现有的老旧代码,就能让原本不兼容的类在新的业务逻辑中协同工作。
- 符合开闭原则(OCP): 增加新的适配器无需修改原有接口或已有类,只需新增适配类即可。
- 解耦业务逻辑与接口转换: 将复杂的格式转换、参数映射等细节封装在适配器内部,客户端调用更简洁干净。
缺点
- 增加系统复杂度: 过多使用适配器会让代码结构显得零乱(明明调用的是 A 接口,底层却跑到了 B 类的逻辑),增加阅读和调试难度。
- 类适配器受限于单继承: 在 Java 等不支持多继承的语言中,类适配器模式一次只能适配一个源类,使用上有局限性。
举个例子
手机充电需要 5V 直流电,但墙上的插座提供的是 220V 交流电。手机不能直接插 220V 插座(接口不兼容,强插会烧毁硬件),我们需要一个电源适配器(Charger Adapter),将 220V 的电压转换为 5V。
1. 源接口/现存类(Adaptee):220V 交流电源
// 现有的墙壁插座,只能输出 220V 电压
public class Output220V {
public int output220V() {
System.out.println("输出交流电:220V");
return 220;
}
}
2. 目标接口(Target):手机需要的 5V 接口
// 手机期望的标准充电接口
public interface Target5V {
int output5V();
}
3. 适配器类(Adapter):电源适配器
利用对象适配器(内部持有一份 Output220V 的引用),将 220V 转化为 5V。
public class PowerAdapter implements Target5V {
private Output220V output220V; // 组合源对象
public PowerAdapter(Output220V output220V) {
this.output220V = output220V;
}
@Override
public int output5V() {
// 获取原始 220V 电压
int src = output220V.output220V();
// 适配器进行变压加工逻辑
int dst = src / 44;
System.out.println("适配器转换:将 " + src + "V 变压为 " + dst + "V 直流电");
return dst;
}
}
4. 客户端调用(Client):手机充电
public class Phone {
// 手机充电只认 Target5V 接口
public void charge(Target5V target5V) {
if (target5V.output5V() == 5) {
System.out.println("电压正常,手机开始充电!");
} else {
System.out.println("电压不匹配,无法充电!");
}
}
}
public class User {
public static void main(String[] args) {
Phone phone = new Phone();
// 现有资源:墙上的 220V 插座
Output220V wallSocket = new Output220V();
// 中间件:插上电源适配器
Target5V adapter = new PowerAdapter(wallSocket);
// 手机连接适配器进行充电
phone.charge(adapter);
}
}
Plaintext
输出交流电:220V
适配器转换:将 220V 变压为 5V 直流电
电压正常,手机开始充电!
适配器模式的实现方式
适用场景
- 系统升级与旧代码重构: 需要复用现有的老代码或第三方模块,但其方法签名/接口不符合新系统的标准接口要求。
- 第三方 SDK 接入统一包装: 例如系统中要集成多家支付 SDK(微信、支付宝、银联),各家的接口命名与参数完全不同,可以通过适配器统一封装为系统自身的 PayService 规范。
- 跨平台/跨框架兼容: 数据库驱动(JDBC Driver)、不同日志框架(SLF4J 对 Log4j/JUL 的适配)等桥接转换场景。




