设计模式每日硬核训练 Day 11:适配器模式(Adapter Pattern)完整讲解与实战应用

🔄 回顾 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):动态增强对象功能,不侵入原类,组合胜继承。

相关推荐
吃饱了得干活15 小时前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器
java·spring cloud
lwx5728017 小时前
探秘InnoDB:搞懂它的内存、线程、磁盘与日志刷盘策略
java·后端
Flynt18 小时前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
plainGeekDev19 小时前
Activity 间传值 → Navigation 参数
android·java·kotlin
plainGeekDev19 小时前
onActivityResult → ActivityResult API
android·java·kotlin
Sunia19 小时前
《AgentX 专栏》10-生产部署:3台2C4G云服务器把企业级Agent真正跑起来的完整方案
java·架构
ZhengEnCi20 小时前
J7A-高级Java工程师面试三道灵魂拷问-深度广度与工程素养的终极检验
java·后端
狼爷2 天前
吃透 Java Function 接口,搞定 99% 的 Stream 场景
java·函数式编程
祎雪双十Gy2 天前
从 DataX 的配置加载说起:我用 FastJson2 做了一个轻量级动态配置管理库
java·后端
小锋java12342 天前
分享一套锋哥原创的SpringBoot4+Vue3宠物领养网站系统
java