【设计模式】结构型模式之适配器模式详解

一、模式定义与核心思想

适配器模式是一种 ​结构型设计模式,其核心作用是 ​将不兼容的接口转换为客户端期望的接口,如同现实世界中的电源转接器。该模式通过创建 ​中间转换层​ 解决接口不匹配问题,实现不同系统间的协同工作。


二、模式结构解析
角色组成:
  1. 目标接口(Target)​
    • 客户端期望使用的接口
    • 抽象类或接口形式存在
  2. 适配者(Adaptee)​
    • 需要被适配的已有组件
    • 通常包含有用功能但接口不兼容
  3. 适配器(Adapter)​
    • 实现目标接口的转换器
    • 封装对适配者的调用
UML图示:
[Client] --> [Target]
               ^
               |
          [Adapter] --> [Adaptee]

三、C++ 实现方式对比
1. 类适配器(通过多重继承)
// 旧版温度传感器(华氏度)
class FahrenheitSensor {
public:
    float getFahrenheit() const {
        return 75.2f;  // 返回华氏温度
    }
};

// 目标接口(摄氏度)
class CelsiusSensor {
public:
    virtual ~CelsiusSensor() = default;
    virtual float getTemperature() const = 0;
};

// 类适配器(多重继承)
class SensorAdapter : public CelsiusSensor, 
                      private FahrenheitSensor {
public:
    float getTemperature() const override {
        // 转换公式:C = (F - 32) * 5/9
        return (getFahrenheit() - 32) * 5 / 9;
    }
};

特点​:

  • 通过继承获得适配者功能
  • 需要支持多重继承的语言
  • 静态绑定,缺乏灵活性
2. 对象适配器(通过组合方式)
class CelsiusSensor {
public:
    virtual ~CelsiusSensor() = default;
    virtual float getCelsius() const = 0;
};

class FahrenheitSensor {
public:
    float getFahrenheit() const { return 75.2f; }
};

class SensorAdapter : public CelsiusSensor {
    std::unique_ptr<FahrenheitSensor> adaptee;
public:
    SensorAdapter(std::unique_ptr<FahrenheitSensor> sensor)
        : adaptee(std::move(sensor)) {}

    float getCelsius() const override {
        return (adaptee->getFahrenheit() - 32) * 5 / 9;
    }
};

特点​:

  • 使用组合方式持有适配者
  • 支持运行时动态适配
  • 更符合组合优于继承原则

四、实际应用场景案例
案例:第三方支付接口适配
// 现有系统接口(目标接口)
class PaymentProcessor {
public:
    virtual void process(double amount) = 0;
    virtual ~PaymentProcessor() = default;
};

// 第三方支付SDK(不兼容接口)
class AlipaySDK {
public:
    void sendPayment(double yuan) {
        std::cout << "支付宝支付: " << yuan << " 元\n";
    }
};

// 适配器实现
class AlipayAdapter : public PaymentProcessor {
    AlipaySDK alipay;
    static constexpr double EXCHANGE_RATE = 0.15; // 美元兑人民币

public:
    void process(double usd) override {
        double yuan = usd / EXCHANGE_RATE;
        alipay.sendPayment(yuan);
    }
};

// 客户端调用
void processPayment(PaymentProcessor& processor) {
    processor.process(100.0); // 支付100美元
}

// 使用示例
AlipayAdapter alipay;
processPayment(alipay);  // 自动转换为人民币支付

五、模式优势与局限
✅ 核心优势:
  1. 接口兼容​:解决新旧系统对接问题
  2. 复用现有代码​:无需修改原始类
  3. 单一职责原则​:分离接口转换与业务逻辑
  4. 开闭原则​:通过适配器扩展而非修改
❗ 使用注意事项:
  1. 不要过度使用​:优先考虑重构接口的可能性
  2. 避免多层嵌套​:超过3层的适配器说明设计存在问题
  3. 性能考量​:代理调用带来的额外开销
  4. 维护成本​:需要同步维护适配器与原始接口

六、与其他模式的关系
模式名称关联点核心区别
代理模式都包装对象代理提供相同接口,适配器改变接口
外观模式简化复杂系统外观定义新接口,适配器复用现有接口
装饰器模式都使用组合结构装饰器增强功能,适配器改变接口

七、现代C++实现技巧
  1. 模板适配器​(编译期适配)
template <typename Adaptee>
class GenericAdapter : public PaymentProcessor {
    Adaptee adaptee;
public:
    void process(double amount) override {
        // 通用转换逻辑
        adaptee.specificProcess(amount * 100); 
    }
};
  1. 智能指针管理生命周期
class SensorAdapter : public CelsiusSensor {
    std::shared_ptr<FahrenheitSensor> adaptee;
public:
    SensorAdapter(std::shared_ptr<FahrenheitSensor> sensor)
        : adaptee(std::move(sensor)) {}
    // ...
};
  1. 使用std::function实现动态适配
using PaymentHandler = std::function<void(double)>;

class LambdaAdapter : public PaymentProcessor {
    PaymentHandler handler;
public:
    LambdaAdapter(PaymentHandler h) : handler(h) {}
    void process(double amount) override {
        handler(amount);
    }
};

// 使用示例
auto wechatAdapter = LambdaAdapter([](double usd) {
    std::cout << "微信支付: " << usd * 7.0 << " CNY\n";
});

八、最佳实践建议
  1. 接口设计阶段​:
    预留适配器扩展点,使用抽象基类定义接口

  2. 遗留系统集成​:
    为每个第三方服务创建独立适配器

  3. 测试策略​:

    • 编写适配器接口的Mock测试
    • 验证边界值的正确转换(如货币单位)
  4. 文档规范​:

    • 明确标注适配器类的作用域
    • 记录接口转换规则(如汇率计算公式)

九、实战经验分享

典型错误案例​:多层嵌套适配器

// 错误示范:双重适配导致维护噩梦
class A { void foo(int); };
class B { void bar(double); };
class C { void baz(std::string); };

class BadAdapter : public Target {
    A a; B b; C c;
public:
    void execute() override {
        int x = /*...*/;
        a.foo(x);
        double y = /*...*/;
        b.bar(y);
        std::string z = /*...*/;
        c.baz(z);
    }
};

优化方案​:

  • 使用外观模式封装复杂子系统
  • 通过领域驱动设计重构统一接口

适配器模式是系统集成的重要工具,但如同任何强大的工具,需要遵循 ​​"最小适配"原则​:只转换必要的接口部分,保持适配器的简洁性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩瀚之水_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值