🔄 回顾 Day 10:模板方法模式小结
在 Day 10 中,我们学习了模板方法模式:
- 它用于定义流程的"骨架",将固定步骤放在父类,具体实现交给子类完成。
- 实现了"统一流程 + 差异化行为"的复用范式。
而今天,我们来学习一个更具桥梁意义的结构型模式------适配器模式(Adapter Pattern)。
一、适配器模式的核心动机
✅ 什么是适配器?
适配器模式用于:
将一个已有接口转换为客户所期望的另一个接口,使原本由于接口不兼容而不能一起工作的类能协同工作。
简单理解:"旧接口 + 新系统 = 用适配器来衔接"
📦 应用动机:
- 第三方库或老代码接口不可更改
- 新系统定义了统一接口,老模块不兼容
- 不希望大规模重构,只想局部"桥接"
二、典型结构图(UML)

+----------------+ +---------------------+
| Target |<-------| Adapter |
+----------------+ +---------------------+
| +request() | | +request() |
+----------------+ | - adaptee: Adaptee |
| +Adapter(adaptee) |
+---------------------+
|
|
+--------------+
| Adaptee |
+--------------+
| +specific() |
+--------------+
✅ 角色解释:
角色 | 职责 |
---|---|
Target | 客户希望使用的接口 |
Adaptee | 现有功能类,接口不兼容 |
Adapter | 适配器,将 Target 接口转换为对 Adaptee 的调用 |
三、分类:类适配器 vs 对象适配器
方式 | 特点 | 实现方式 |
---|---|---|
类适配器 | 通过继承实现,适用于单继承结构 | class Adapter : public Adaptee, public Target |
对象适配器 | 通过组合实现,更灵活、推荐使用 | Adapter 包含 Adaptee 指针或引用 |
四、C++ 实现:日志系统适配不同输出端
🎯 场景背景
系统原本只支持写入 std::ofstream
文件,现在希望支持第三方 LegacyLogger
类(它只能使用 writeLegacy()
方法输出)。为了统一日志接口,我们采用适配器模式。
✅ Target 接口(期望的日志接口)
cpp
class ILogger {
public:
virtual void log(const std::string& message) = 0;
virtual ~ILogger() = default;
};
✅ Adaptee(第三方或老接口)
cpp
class LegacyLogger {
public:
void writeLegacy(const std::string& text) {
std::cout << "[Legacy] " << text << std::endl;
}
};
✅ Adapter(桥接类)
cpp
class LoggerAdapter : public ILogger {
private:
LegacyLogger* legacy_;
public:
LoggerAdapter(LegacyLogger* legacy) : legacy_(legacy) {}
void log(const std::string& message) override {
legacy_->writeLegacy(message);
}
};
✅ Client 使用
cpp
void runLogger(ILogger* logger) {
logger->log("程序已启动");
}
int main() {
LegacyLogger legacy;
LoggerAdapter adapter(&legacy);
runLogger(&adapter); // 无需修改 runLogger,实现日志模块适配
return 0;
}
五、实战场景举例(工业开发常见)
应用场景 | 适配器用途说明 |
---|---|
Qt5 与 Qt6 事件兼容 | Qt6 接口变化较大,编写 Qt5 兼容适配层 |
驱动程序接口迁移 | 新版驱动框架要求统一接口,旧驱动通过适配器连接 |
通信协议切换 | 适配器桥接老协议栈与新通信接口 |
Web 服务封装 | 使用适配器将第三方 SDK 接口封装为内部统一 API 接口 |
配置加载兼容 | 旧项目使用 INI,新项目使用 JSON,使用适配器统一配置读取方式 |
六、与桥接、装饰器、策略的对比
模式 | 意图 | 典型使用时机 |
---|---|---|
Adapter | 接口转换,兼容旧系统 | 连接新旧系统,替换不可更改类 |
Bridge | 分离接口与实现(双维度变化) | 需要独立扩展实现与接口两个维度 |
Decorator | 增强功能 | 不改原始类而增加功能 |
Strategy | 算法封装、运行时切换 | 多算法切换 |
七、面试回答模板
"我们在设备接入框架中使用适配器模式非常频繁,比如将老式协议数据转换为平台统一数据格式,或者在引入第三方模块时用适配器封装它的日志接口,统一为我们的
ILogger
接口,便于替换与测试。适配器帮助我们降低耦合、提升兼容性。"
✅ 加分点:强调对象适配器 vs 类适配器的选择理由。
八、口诀记忆
"老接口,新系统,中间加桥梁;不改老代码,外部巧适配。"
九、明日预告:Day 12
装饰器模式(Decorator Pattern):动态增强对象功能,不侵入原类,组合胜继承。