适配器模式
约 1459 字大约 5 分钟
理论设计模式
2026-04-07
适配器模式(Adapter Pattern)是一种结构型设计模式,它的核心目标是将一个类的接口转换成客户端所期望的另一个接口,使得原本因接口不兼容而无法协同工作的类可以一起工作。
简单来说,适配器模式就像生活中的“转接头”或“转换器”,例如将美标插头的笔记本电脑插入国标插座,或者将TF卡插入SD卡槽,它在不修改原有代码的前提下,实现了接口的兼容。
🎯 为什么需要适配器模式?
在软件开发中,我们经常会遇到以下场景:
- 复用现有代码:需要复用一个功能完善的类(如第三方库、遗留系统组件),但它的接口与当前系统要求的接口不一致。
- 遵守开闭原则:不能或不想修改原有类的代码(例如没有源码、修改成本高)。
- 统一接口规范:需要为不同的、不兼容的接口提供一个统一的调用方式。
此时,适配器模式提供了一种“非侵入式”的解决方案:通过新增一个“适配器”类来桥接新旧接口,实现无缝集成。
🏗️ 适配器模式的结构
适配器模式主要包含以下三个角色:
| 角色 | 作用与职责 |
|---|---|
| 目标接口(Target) | 定义客户端所期望的标准接口。客户端通过该接口调用服务,无需关心具体实现。 |
| 被适配者(Adaptee) | 已存在的、具有所需功能但接口与Target不兼容的类。通常来自第三方库或遗留系统。 |
| 适配器(Adapter) | 实现Target接口,并内部持有或继承Adaptee,负责将Target接口的调用转换为对Adaptee的调用。 |
适配器模式主要有两种实现方式:对象适配器和类适配器。
🚀 对象适配器 vs 类适配器
对象适配器(推荐)
对象适配器通过组合的方式实现,适配器内部持有一个被适配者(Adaptee)的实例。这是更常用、更灵活的方式,因为它遵循了“组合优于继承”的原则,降低了代码间的耦合度。
实战案例:统一支付接口 假设系统需要统一的 Payment 接口,但已有的微信支付和支付宝支付的接口方法名不同。
定义目标接口与被适配者
// 1.1 目标接口:系统期望的统一支付接口 public interface Payment { String pay(double amount); } // 1.2 被适配者:已有的微信支付类 public class WeChatPay { public String weChatPay(double money) { return "微信支付成功:" + money + "元"; } } // 1.3 被适配者:已有的支付宝支付类 public class Alipay { public String aliPay(double total) { return "支付宝支付成功:" + total + "元"; } }创建对象适配器
// 2.1 微信支付适配器 public class WeChatPayAdapter implements Payment { private WeChatPay weChatPay; // 持有被适配对象 public WeChatPayAdapter(WeChatPay weChatPay) { this.weChatPay = weChatPay; } @Override public String pay(double amount) { // 将目标接口调用转换为被适配者的方法调用 return weChatPay.weChatPay(amount); } } // 2.2 支付宝支付适配器 public class AlipayAdapter implements Payment { private Alipay alipay; public AlipayAdapter(Alipay alipay) { this.alipay = alipay; } @Override public String pay(double amount) { return alipay.aliPay(amount); } }客户端调用
public class Client { public static void main(String[] args) { // 客户端只依赖Payment接口 Payment payment = new WeChatPayAdapter(new WeChatPay()); System.out.println(payment.pay(100.0)); payment = new AlipayAdapter(new Alipay()); System.out.println(payment.pay(200.0)); } }
类适配器
类适配器通过多重继承实现,适配器同时继承目标接口和被适配者。这种方式在Java等单继承语言中存在局限,因为它要求被适配者必须是一个类,且会占用唯一的继承名额,导致耦合更紧。
// 类适配器示例(Java中不推荐)
public class WeChatPayClassAdapter extends WeChatPay implements Payment {
@Override
public String pay(double amount) {
// 直接调用父类方法
return super.weChatPay(amount);
}
}✅ 适配器模式的优缺点
优点
- 提高复用性:可以在不修改原有类代码的前提下,复用其功能。
- 解耦:客户端只依赖目标接口(Target),与具体的被适配者(Adaptee)解耦。
- 符合开闭原则:增加新的适配器即可支持新的被适配者,无需修改现有代码。
- 透明性好:客户端无需知道背后使用的是适配器还是原生实现。
缺点
- 增加系统复杂度:每种不兼容都需要一个适配器,适配器过多会使代码结构变得复杂。
- 类适配器受限:在单继承语言中,类适配器的实现受到限制。
📝 常见应用场景
- 老系统迁移/改造:将旧系统的接口适配为新系统期望的接口,实现新老兼容。
- 第三方SDK封装:对外暴露一套统一接口,内部通过各种适配器接入不同厂商的SDK(如支付、地图、登录等)。
- 日志框架整合:应用使用SLF4J(Target),底层可能是Log4j、Logback(Adaptee),SLF4J通过适配器桥接了它们。
- Spring MVC中的HandlerAdapter:将不同类型的Controller适配为统一的处理流程。
🔍 与其他模式的区别
- 与外观模式:外观模式的目的是简化一个复杂系统的接口;而适配器模式的目的是转换一个已有接口,使其兼容另一个接口。
- 与装饰器模式:装饰器模式在不改变对象接口的前提下增强其功能;适配器模式则会改变对象的接口。
- 与代理模式:代理模式通常为对象提供一个相同的接口,以控制对其的访问;适配器模式则提供一个不同的接口。
