设计模式每日硬核训练 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 接口(期望的日志接口)

class ILogger {
public:
    virtual void log(const std::string& message) = 0;
    virtual ~ILogger() = default;
};

✅ Adaptee(第三方或老接口)

class LegacyLogger {
public:
    void writeLegacy(const std::string& text) {
        std::cout << "[Legacy] " << text << std::endl;
    }
};

✅ Adapter(桥接类)

class LoggerAdapter : public ILogger {
private:
    LegacyLogger* legacy_;
public:
    LoggerAdapter(LegacyLogger* legacy) : legacy_(legacy) {}

    void log(const std::string& message) override {
        legacy_->writeLegacy(message);
    }
};

✅ Client 使用

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值