设计模式之适应设计模式_Adapter模式_加一个适配器以便复用
一、Adapter(适配器)设计模式
1、模式概述
适配器模式(Adapter Pattern) 是一种 结构型设计模式,其核心目标是:
适配器模式 = 接口翻译官:
-
将一个类的接口转换成客户端所期望的另一个接口,使原本因接口不兼容而不能一起工作的类可以协同工作。
-
它不做功能增强,也不改变行为,只是 在不修改原有代码的前提下,让不兼容的接口“说同一种语言”。
1)两种实现方式
| 类型 | 实现机制 | 特点 |
|---|---|---|
| 类适配器 | 通过 继承 被适配类(Adaptee) |
仅适用于支持多重继承的语言(如 C++),Java 中因单继承限制使用较少 |
| 对象适配器 | 通过 组合/委托 持有被适配对象 | 更灵活、推荐方式,符合“组合优于继承”原则 |
2)适配器 vs 装饰器:关键区别
两者都被称为 包装模式(Wrapper Pattern),但目的截然不同:
- 适配器:“让它能用”(接口不匹配 → 匹配)
- 装饰器:“让它更好用”(功能不足 → 增强)
| 模式 | 目的 | 接口变化 | 典型用途 |
|---|---|---|---|
| Adapter(适配器) | 转换接口,解决兼容性问题 | 改变或统一接口(旧 → 新) | 集成遗留系统、第三方库封装 |
| Decorator(装饰器) | 增强功能,动态添加职责 | 保持原有接口不变 | 日志、缓存、权限校验等横切关注点 |
3)使用场景
- 需要使用一个已存在的类,但其接口不符合当前需求;
- 想创建一个可复用的类,与不相关或不可预见的类协同工作;
- 需要适配多个已有子类,但不想为每个子类编写适配逻辑(可用对象适配器统一处理)。
在实际开发中:
- 优先使用对象适配器(组合);
- 当需要适配多个相似类时,可结合 工厂模式 动态创建适配器;
Java标准库中的Arrays.asList()、InputStreamReader等都是适配器的经典应用。
2、示例场景:电压适配类比
我们有一个 100V 的电器(Banner),但插座提供的是 220V 接口(Print)。
通过 适配器(Adapter),我们让 100V 设备“看起来像”支持 220V 接口,从而无缝接入系统。
1)被适配的现有类(Adaptee)
这是已存在的类,无法修改或不应修改(如第三方库)。
/**
* Adaptee(被适配者)—— 现有系统中的类,接口不符合新需求
*/
public class Banner {
private final String text;
public Banner(String text) {
this.text = text;
}
public void showWithParen() {
System.out.println("(" + text + ")");
}
public void showWithAster() {
System.out.println("*" + text + "*");
}
}
2)目标接口(Target)
/**
* Target(目标接口)—— 客户端期望的接口
*/
public interface Print {
void printWeak(); // 弱调用 → 对应 (text)
void printStrong(); // 强调用 → 对应 *text*
}
3)方式一:类适配器(继承)
Java不支持多重继承,若Banner已继承其他类,则无法使用此方式。- 违反“合成复用原则”。

/**
* Class Adapter:通过继承 Banner 并实现 Print 接口
*/
public class PrintBanner extends Banner implements Print {
public PrintBanner(String text) {
super(text);
}
@Override
public void printWeak() {
showWithParen();
}
@Override
public void printStrong() {
showWithAster();
}
}
4)方法2:对象适配器(委托/组合) 推荐
- 灵活,可适配任意
Banner子类 - 符合开闭原则(对扩展开放,对修改关闭)
- 支持运行时动态替换被适配对象
/**
* Object Adapter:通过组合 Banner 实现适配
*/
public class PrintBanner implements Print {
private final Banner banner;
public PrintBanner(String text) {
this.banner = new Banner(text);
}
@Override
public void printWeak() {
banner.showWithParen();
}
@Override
public void printStrong() {
banner.showWithAster();
}
}
5) 客户端测试
客户端 完全不知道
Banner的存在,只与
public class Main {
public static void main(String[] args) {
Print printer = new PrintBanner("Hello");
printer.printWeak(); // 输出: (Hello)
printer.printStrong(); // 输出: *Hello*
}
}
3、模式角色总结
| 角色 | 职责 | 示例 |
|---|---|---|
| Target(目标接口) | 定义客户端使用的接口 | Print |
| Adaptee(被适配者) | 已存在的、接口不兼容的类 | Banner |
| Adapter(适配器) | 转换 Adaptee 接口为 Target 接口 | PrintBanner |
| Client(客户端) | 使用 Target 接口完成业务逻辑 | Main |
1)UML 类适配器模式(使用继承)

2)UML 对象适配器模式(使用委托)



