适配器模式 (Adapter) 全面讲解
学习笔记
设计模式
适配器模式
Java
面向对象
软件设计
编程实践
本文全面讲解了适配器模式,包括其定义、适用场景、实现方式以及在实际编程中的应用,旨在帮助读者深入理解并掌握这一重要的设计模式。
date: 2025-06-22T20:04:00 tags:
- 设计模式
- Java
- 面向对象
- 复习
适配器模式 (Adapter) 全面讲解
1. 什么是适配器模式?
适配器模式是结构型设计模式,用于让不兼容的接口能够协同工作。
- 核心思想:通过一个中间层(适配器)转换接口,类似电源插头转换器。
- 类比:
- Type-C转3.5mm耳机接口
- 翻译官(连接语言不通的两人)
🔹 适用场景
- 整合第三方库/旧系统时接口不匹配。
- 需要统一多个类的接口(如不同品牌的充电协议)。
2. 为什么需要适配器模式?
问题场景
假设有一个新系统调用ModernPrinter打印,但旧系统的LegacyPrinter接口不同:
// 新系统的接口(目标接口)
interface ModernPrinter {
void print(String text);
}
// 旧系统的类(需适配的类)
class LegacyPrinter {
void printDocument(String content, int copies) {
for (int i = 0; i < copies; i++) {
System.out.println("旧打印机打印: " + content);
}
}
}
问题:无法直接调用LegacyPrinter,因为接口不兼容!
3. 适配器模式的两种实现
3.1 类适配器(继承方式)
通过继承旧类实现适配(需支持多继承,Java不适用,但可模拟)。
// 适配器类(继承LegacyPrinter并实现ModernPrinter)
class ClassAdapter extends LegacyPrinter implements ModernPrinter {
@Override
public void print(String text) {
printDocument(text, 1); // 调用父类方法,固定copies=1
}
}
3.2 对象适配器(组合方式,推荐)
通过持有旧类的实例实现适配(更灵活)。
class ObjectAdapter implements ModernPrinter {
private LegacyPrinter legacyPrinter; // 组合旧类
public ObjectAdapter(LegacyPrinter legacyPrinter) {
this.legacyPrinter = legacyPrinter;
}
@Override
public void print(String text) {
legacyPrinter.printDocument(text, 1); // 委托给旧类
}
}
4. 完整示例代码(对象适配器)
步骤1:定义目标接口(新系统)
interface ModernPrinter {
void print(String text);
}
步骤2:定义被适配者(旧系统)
class LegacyPrinter {
void printDocument(String content, int copies) {
for (int i = 0; i < copies; i++) {
System.out.println("旧打印机打印: " + content);
}
}
}
步骤3:实现适配器
class PrinterAdapter implements ModernPrinter {
private LegacyPrinter legacyPrinter;
public PrinterAdapter(LegacyPrinter legacyPrinter) {
this.legacyPrinter = legacyPrinter;
}
@Override
public void print(String text) {
legacyPrinter.printDocument(text, 1); // 适配逻辑
}
}
步骤4:客户端调用
public class Client {
public static void main(String[] args) {
// 旧系统对象
LegacyPrinter legacyPrinter = new LegacyPrinter();
// 适配器转换
ModernPrinter adapter = new PrinterAdapter(legacyPrinter);
// 新系统统一调用
adapter.print("Hello World");
// 输出:旧打印机打印: Hello World
}
}
5. 关键点总结
| 对比项 | 类适配器 | 对象适配器(推荐) |
|---|---|---|
| 实现方式 | 继承被适配者 | 组合被适配者 |
| 灵活性 | 低(Java不支持多继承) | 高(可适配多个不同类) |
| 复杂度 | 简单 | 略高 |
🔹 适配器模式的优点
- 解耦:客户端与被适配者无需直接交互。
- 复用性:可复用现有类(如旧系统代码)。
🔹 常见应用
- Java I/O中的
InputStreamReader(适配InputStream到Reader)。 - Spring MVC的
HandlerAdapter(适配不同Controller接口)。
6. 互动实践
问题1:以下代码是哪种适配器?
class Adapter extends OldSystem implements NewInterface {
@Override
public void newMethod() {
oldMethod();
}
}
答案:类适配器(通过继承实现)。
问题2:如何用对象适配器实现USB转Type-C?
任务:
- 被适配者:
USB类(有transferData()方法)。 - 目标接口:
TypeC(需fastTransfer()方法)。 - 补全适配器代码:
class USBToTypeCAdapter implements TypeC {
private USB usb;
// 你的代码...
}
7. 考试练习题
题目1(概念题)
适配器模式的主要作用是?
A. 扩展对象功能
B. 转换接口以便复用
C. 隐藏对象创建细节
D. 优化算法性能
答案:B
题目2(代码填空)
补全对象适配器模式的代码:
interface NewService {
void execute();
}
class OldService {
void run() { System.out.println("旧服务运行"); }
}
class Adapter implements NewService {
private OldService oldService;
public Adapter(____ oldService) { // 填空1
this.oldService = oldService;
}
@Override
public void execute() {
____.run(); // 填空2
}
}
答案:
OldServiceoldService
题目3(设计题)
现有两个不兼容的支付接口:
- 支付宝:
Alipay.pay(double money) - 微信支付:
WeChatPay.payment(double amount)
设计一个适配器,统一调用接口为Payment.pay(double money)。