文章目录
- 1. 引言:一个现实中的“接口不兼容”问题
- 2. 什么是适配器模式
- GoF 定义
- 3. 适配器模式的核心思想
- 4. 适配器模式的角色组成
- 5. 对象适配器(最常用,推荐)
- 5.1 目标接口
- 5.2 被适配者
- 5.3 适配器实现
- 5.4 客户端使用
- 5.5 特点分析
- 6. 类适配器(基于继承)
- 6.1 适配器实现
- 6.2 特点
- 7. 接口适配器(缺省适配器)
- 7.1 使用背景
- 7.2 抽象适配器
- 7.3 客户端使用
- 8. 适配器模式的典型应用场景
- 9. JDK 中的适配器模式
- `InputStreamReader`
- 10. 适配器 vs 代理 vs 装饰器
- 11. 适配器模式的优点
- 12. 适配器模式的缺点
- 13. 何时使用适配器模式
- 适合使用
- 不适合使用
- 参考
1. 引言:一个现实中的“接口不兼容”问题
在实际开发中,我们经常会遇到这样的场景:
- 引入第三方库,但它的接口与你现有系统不一致
- 老系统接口无法修改,但新代码已经按新接口编写
- 不同模块由不同团队开发,接口设计不统一
例如:
// 系统期望的接口voidrequest();// 现有类提供的接口voidspecificRequest();这时你面临一个选择:
- 修改已有类(风险高、不可控)
- 在客户端做各种 if-else 适配(代码混乱)
有没有一种方式,在不修改原有代码的前提下,让接口“对得上”?
答案就是——适配器模式。
2. 什么是适配器模式
GoF 定义
将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
一句话理解:
适配器模式 = 接口转换器。
3. 适配器模式的核心思想
适配器模式关注的不是功能增强(那是代理 / 装饰器),而是:
解决“接口不匹配”的问题。
它的本质是:
- 客户端依赖目标接口(Target)
- 适配器在内部调用已有接口(Adaptee)
- 对外“伪装”成客户端需要的接口
4. 适配器模式的角色组成
适配器模式通常包含三个角色:
- 目标接口(Target)
- 客户端期望的接口,即当前系统业务所期待的接口,它可以是抽象类或接口。
- 被适配者(Adaptee)
- 已存在但接口不兼容的类,它是被访问和适配的现存组件库中的组件接口。
- 适配器(Adapter)
- 进行接口转换,它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
5. 对象适配器(最常用,推荐)
5.1 目标接口
publicinterfaceTarget{voidrequest();}5.2 被适配者
publicclassAdaptee{publicvoidspecificRequest(){System.out.println("原有接口的实现");}}5.3 适配器实现
publicclassObjectAdapterimplementsTarget{privatefinalAdapteeadaptee;publicObjectAdapter(Adapteeadaptee){this.adaptee=adaptee;}@Overridepublicvoidrequest(){adaptee.specificRequest();}}5.4 客户端使用
Targettarget=newObjectAdapter(newAdaptee());target.request();5.5 特点分析
- 基于组合(推荐)
- 灵活、安全
- 可适配多个被适配者
6. 类适配器(基于继承)
6.1 适配器实现
publicclassClassAdapterextendsAdapteeimplementsTarget{@Overridepublicvoidrequest(){specificRequest();}}6.2 特点
- 基于继承
- 只能适配一个类
- 不支持多继承(Java 限制)
7. 接口适配器(缺省适配器)
7.1 使用背景
当接口中方法很多,但你只想实现其中一部分:
publicinterfaceListener{voidonClick();voidonDoubleClick();voidonLongClick();}7.2 抽象适配器
publicabstractclassListenerAdapterimplementsListener{@OverridepublicvoidonClick(){}@OverridepublicvoidonDoubleClick(){}@OverridepublicvoidonLongClick(){}}7.3 客户端使用
publicclassClickListenerextendsListenerAdapter{@OverridepublicvoidonClick(){System.out.println("处理点击事件");}}8. 适配器模式的典型应用场景
- 老系统改造
- 第三方 SDK 接入
- 统一接口规范
- 系统迁移、重构
- 框架设计
9. JDK 中的适配器模式
InputStreamReader
InputStreamin=newFileInputStream("test.txt");Readerreader=newInputStreamReader(in);InputStream→ 字节流Reader→ 字符流InputStreamReader就是适配器
10. 适配器 vs 代理 vs 装饰器
| 模式 | 核心目的 |
|---|---|
| 适配器 | 接口转换 |
| 代理 | 控制访问 |
| 装饰器 | 功能增强 |
关注点不同,切勿混用。
11. 适配器模式的优点
- 复用已有代码
- 符合开闭原则
- 解耦客户端与实现
- 提高系统灵活性
12. 适配器模式的缺点
- 增加系统复杂度
- 过度使用会导致结构混乱
- 不易调试(调用链变长)
13. 何时使用适配器模式
适合使用
- 接口不兼容,但又不能改原代码
- 需要快速集成第三方库
- 系统升级、兼容旧接口
不适合使用
- 能直接修改接口的场景
- 系统接口设计初期
参考
适配器模式 | 菜鸟教程
适配器模式-百度百科
《图解设计模式》
适配器 - Java教程 - 廖雪峰的官方网站
适配器设计模式(封装器模式)