跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++Pay算法

设计模式实战:C++ 装饰者模式与适配器模式的应用

综述由AI生成C++ 中装饰者模式与适配器模式的核心思想及实现细节。通过电商订单优惠系统和支付网关案例,展示了如何利用装饰者模式动态扩展对象功能,避免继承导致的类爆炸;利用适配器模式解决接口不兼容问题,实现第三方库集成。内容涵盖角色划分、代码示例、智能指针管理、优缺点分析及避坑指南,帮助开发者在实际业务场景中灵活运用两种结构型设计模式,构建灵活可扩展的系统架构。

JavaCoder发布于 2026/2/5更新于 2026/5/293.1K 浏览
设计模式实战:C++ 装饰者模式与适配器模式的应用

设计模式实战:C++ 中装饰者模式与适配器模式的应用

本章学习目标与重点

  • 掌握装饰者模式的核心设计思想、角色划分及 C++ 实现细节(动态扩展功能、避免继承臃肿)
  • 理解适配器模式的两种实现方式(类适配器、对象适配器)及适用场景
  • 能够结合实际业务场景(如功能增强、接口兼容)灵活运用两种模式
  • 解决模式应用中的关键问题(如装饰者层级管理、适配器接口匹配、类型转换安全)

重点: 装饰者模式的动态扩展逻辑、适配器模式的接口适配技巧、两种模式的组合使用场景

设计模式进阶认知:结构型模式的核心价值

在 C++ 开发中,结构型设计模式专注于解决'类与对象的组合方式'问题,通过合理的结构组合,实现功能复用、接口兼容或功能扩展。相比行为型模式关注'对象交互',结构型模式更侧重'对象组装'。

为什么需要结构型设计模式?

实际开发中,我们常遇到以下结构相关的问题:

  • 需为一个对象动态添加额外功能(如给商品订单添加优惠券、积分抵扣、满减等功能),若使用继承会导致类数量爆炸;
  • 现有类的接口与目标接口不匹配(如第三方库的接口格式与项目现有接口不一致),直接使用会导致代码耦合严重;
  • 类的功能过于复杂,需拆分但又不想破坏原有接口;
  • 希望复用多个类的功能,但又不能通过多重继承实现(避免菱形继承、代码冗余)。

结构型模式通过标准化的组合方式,将'核心功能'与'扩展功能''现有接口'与'目标接口'分离,例如装饰者模式通过组合实现功能动态扩展,适配器模式通过转换实现接口兼容,从而解决上述问题。

结构型模式的核心设计原则

结构型模式的设计始终围绕以下原则展开,这也是本章两种模式的核心指导思想:

  1. 合成复用原则:优先使用对象组合,而非类继承,实现功能复用(减少耦合、提升灵活性);
  2. 开放 - 封闭原则:扩展功能时无需修改原有代码,通过新增类实现;
  3. 接口隔离原则:适配或扩展时,不依赖不必要的接口,保持接口简洁;
  4. 依赖倒置原则:依赖抽象接口,不依赖具体实现(如装饰者与被装饰者依赖同一抽象)。

装饰者模式:动态扩展对象功能的灵活方案

装饰者模式(Decorator Pattern)又称包装器模式(Wrapper Pattern),其核心思想是'动态地给一个对象添加一些额外的职责,就像在墙上刷油漆一样,不改变对象本身的结构,却能增强其功能'。

核心角色与设计逻辑
1. 核心角色
  • 抽象组件(Component):定义被装饰对象和装饰者的共同接口,是装饰者模式的基础;
  • 具体组件(ConcreteComponent):被装饰的核心对象,实现抽象组件接口,包含核心功能;
  • 抽象装饰者(Decorator):继承自抽象组件,持有一个抽象组件的引用,定义装饰者的统一接口;
  • 具体装饰者(ConcreteDecorator):实现抽象装饰者接口,通过调用被装饰对象的方法,再添加额外功能。
2. 设计逻辑

抽象装饰者与具体组件继承自同一抽象组件,确保装饰者与被装饰者类型一致,可相互替换;抽象装饰者持有抽象组件的引用,通过组合方式将装饰者与被装饰者关联,实现'装饰者包裹被装饰者'的嵌套结构,从而动态添加功能。

适用场景
  • 需动态为对象添加或移除功能(如订单支付时,根据用户选择动态添加优惠券、积分抵扣等);
  • 避免使用继承导致的类爆炸(如一个核心功能有多种扩展功能,组合方式多样);
  • 扩展功能需灵活组合(如商品可以同时享受'折扣 + 优惠券 + 满减'多重优惠);
  • 不希望修改原有类的代码(符合开放 - 封闭原则)。
基础实现:电商订单优惠系统(C++ 示例)

以'电商订单优惠系统'为例:订单(具体组件)可享受多种优惠(具体装饰者),如优惠券抵扣、积分抵扣、满减优惠,且优惠可灵活组合(如同时使用优惠券 + 积分),使用装饰者模式可动态扩展优惠功能。

步骤 1:定义抽象组件(订单接口)
#include 

  std;


  {
:
    
    = ;
    
    = ;
     ~() {}
};
<iostream>
#include <string>
using
namespace
// 抽象组件:订单接口
class
OrderComponent
public
// 纯虚函数:计算最终价格
virtual float CalculateFinalPrice() const
0
// 纯虚函数:获取订单描述
virtual string GetOrderDescription() const
0
virtual
OrderComponent
步骤 2:实现具体组件(基础订单)
// 具体组件:基础订单(无任何优惠)
class BasicOrder : public OrderComponent {
private:
    string orderId;      // 订单 ID
    float originalPrice; // 商品原价

public:
    BasicOrder(const string& id, float price) : orderId(id), originalPrice(price) {
        if (price < 0) {
            throw invalid_argument("商品原价不能为负数!");
        }
    }

    // 计算最终价格(无优惠,返回原价)
    float CalculateFinalPrice() const override {
        return originalPrice;
    }

    // 获取订单描述
    string GetOrderDescription() const override {
        return "订单 [" + orderId + "] 基础价格:" + to_string(originalPrice) + "元";
    }

    // 获取原价(供装饰者使用)
    float GetOriginalPrice() const {
        return originalPrice;
    }
};
步骤 3:定义抽象装饰者(优惠装饰器接口)
// 抽象装饰者:优惠装饰器
class DiscountDecorator : public OrderComponent {
private:
    // 持有抽象组件的引用(核心:组合方式关联被装饰对象)
    OrderComponent* component;

protected:
    // 保护方法:获取被装饰对象(供子类使用)
    OrderComponent* GetComponent() const {
        return component;
    }

public:
    // 构造函数:传入被装饰的订单组件
    DiscountDecorator(OrderComponent* comp) : component(comp) {
        if (comp == nullptr) {
            throw invalid_argument("被装饰的订单组件不能为空!");
        }
    }

    // 析构函数:不负责销毁被装饰对象(由客户端管理)
    ~DiscountDecorator() {}

    // 转发计算价格的调用(子类可扩展)
    float CalculateFinalPrice() const override {
        return component->CalculateFinalPrice();
    }

    // 转发订单描述的调用(子类可扩展)
    string GetOrderDescription() const override {
        return component->GetOrderDescription();
    }
};
步骤 4:实现具体装饰者(各种优惠)
// 具体装饰者 1:优惠券抵扣(固定金额抵扣)
class CouponDecorator : public DiscountDecorator {
private:
    float couponAmount; // 优惠券金额

public:
    CouponDecorator(OrderComponent* comp, float amount) : DiscountDecorator(comp), couponAmount(amount) {
        if (amount <= 0) {
            throw invalid_argument("优惠券金额必须大于 0!");
        }
    }

    // 计算最终价格:基础价格 - 优惠券金额(最低为 0)
    float CalculateFinalPrice() const override {
        float basePrice = GetComponent()->CalculateFinalPrice();
        float finalPrice = basePrice - couponAmount;
        return finalPrice < 0 ? 0 : finalPrice;
    }

    // 扩展订单描述:添加优惠券信息
    string GetOrderDescription() const override {
        return GetComponent()->GetOrderDescription() + " + 优惠券抵扣" + to_string(couponAmount) + "元";
    }
};

// 具体装饰者 2:积分抵扣(100 积分抵扣 1 元)
class PointsDecorator : public DiscountDecorator {
private:
    int points; // 抵扣积分

public:
    PointsDecorator(OrderComponent* comp, int pts) : DiscountDecorator(comp), points(pts) {
        if (pts <= 0) {
            throw invalid_argument("抵扣积分必须大于 0!");
        }
    }

    // 计算最终价格:基础价格 - 积分抵扣金额(积分/100)
    float CalculateFinalPrice() const override {
        float basePrice = GetComponent()->CalculateFinalPrice();
        float discountAmount = points / 100.0f; // 100 积分=1 元
        float finalPrice = basePrice - discountAmount;
        return finalPrice < 0 ? 0 : finalPrice;
    }

    string GetOrderDescription() const override {
        return GetComponent()->GetOrderDescription() + " + " + to_string(points) + "积分抵扣" + to_string(points / 100.0f) + "元";
    }
};

// 具体装饰者 3:满减优惠(满 X 减 Y)
class FullReduceDecorator : public DiscountDecorator {
private:
    float fullAmount; // 满减门槛
    float reduceAmount; // 减免金额

public:
    FullReduceDecorator(OrderComponent* comp, float full, float reduce) : DiscountDecorator(comp), fullAmount(full), reduceAmount(reduce) {
        if (full <= 0 || reduce <= 0) {
            throw invalid_argument("满减门槛和减免金额必须大于 0!");
        }
        if (reduce >= full) {
            throw invalid_argument("减免金额不能大于等于满减门槛!");
        }
    }

    // 计算最终价格:满足门槛则减免
    float CalculateFinalPrice() const override {
        float basePrice = GetComponent()->CalculateFinalPrice();
        float finalPrice = basePrice;
        if (basePrice >= fullAmount) {
            finalPrice = basePrice - reduceAmount;
        }
        return finalPrice < 0 ? 0 : finalPrice;
    }

    string GetOrderDescription() const override {
        return GetComponent()->GetOrderDescription() + " + 满" + to_string(fullAmount) + "减" + to_string(reduceAmount) + "元";
    }
};
步骤 5:客户端使用示例(灵活组合优惠)
int main() {
    try {
        // 1. 创建基础订单(原价 1500 元)
        OrderComponent* basicOrder = new BasicOrder("ORD20240502001", 1500.0f);
        cout << "=== 基础订单 ===" << endl;
        cout << basicOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << basicOrder->CalculateFinalPrice() << "元" << endl;

        // 2. 仅使用优惠券(抵扣 200 元)
        OrderComponent* couponOrder = new CouponDecorator(basicOrder, 200.0f);
        cout << "\n=== 基础订单 + 优惠券 ===" << endl;
        cout << couponOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << couponOrder->CalculateFinalPrice() << "元" << endl;

        // 3. 优惠券 + 积分抵扣(500 积分=5 元)
        OrderComponent* couponPointsOrder = new PointsDecorator(couponOrder, 500);
        cout << "\n=== 基础订单 + 优惠券 + 积分 ===" << endl;
        cout << couponPointsOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << couponPointsOrder->CalculateFinalPrice() << "元" << endl;

        // 4. 优惠券 + 积分 + 满 1000 减 150
        OrderComponent* fullReduceOrder = new FullReduceDecorator(couponPointsOrder, 1000.0f, 150.0f);
        cout << "\n=== 基础订单 + 优惠券 + 积分 + 满减 ===" << endl;
        cout << fullReduceOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << fullReduceOrder->CalculateFinalPrice() << "元" << endl;

        // 5. 另一种组合:基础订单 + 满减(单独使用满减)
        OrderComponent* onlyFullReduceOrder = new FullReduceDecorator(basicOrder, 1000.0f, 150.0f);
        cout << "\n=== 基础订单 + 满减 ===" << endl;
        cout << onlyFullReduceOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << onlyFullReduceOrder->CalculateFinalPrice() << "元" << endl;

        // 6. 释放资源(注意:装饰者不负责销毁被装饰对象,需手动按层级释放)
        delete fullReduceOrder;
        delete couponPointsOrder;
        delete couponOrder;
        delete onlyFullReduceOrder;
        delete basicOrder;
    } catch (const exception& e) {
        cout << "错误:" << e.what() << endl;
    }
    return 0;
}
运行结果
=== 基础订单 === 订单 [ORD20240502001] 基础价格:1500.000000 元 最终价格:1500 元
=== 基础订单 + 优惠券 === 订单 [ORD20240502001] 基础价格:1500.000000 元 + 优惠券抵扣 200.000000 元 最终价格:1300 元
=== 基础订单 + 优惠券 + 积分 === 订单 [ORD20240502001] 基础价格:1500.000000 元 + 优惠券抵扣 200.000000 元 + 500 积分抵扣 5.000000 元 最终价格:1295 元
=== 基础订单 + 优惠券 + 积分 + 满减 === 订单 [ORD20240502001] 基础价格:1500.000000 元 + 优惠券抵扣 200.000000 元 + 500 积分抵扣 5.000000 元 + 满 1000 减 150.000000 元 最终价格:1145 元
=== 基础订单 + 满减 === 订单 [ORD20240502001] 基础价格:1500.000000 元 + 满 1000 减 150.000000 元 最终价格:1350 元
进阶优化:智能指针管理与多层装饰增强

基础实现中,手动管理装饰者层级的内存容易出错(如遗漏释放、重复释放),且装饰者功能相对简单。以下优化方案使用智能指针自动管理内存,并新增'限时折扣'装饰者,支持更复杂的多层嵌套。

优化 1:使用智能指针管理内存
#include <memory>

int main() {
    try {
        // 使用 shared_ptr 自动管理内存,无需手动释放
        shared_ptr<OrderComponent> basicOrder = make_shared<BasicOrder>("ORD20240502002", 2000.0f);

        // 组合优惠:优惠券(300 元)+ 限时折扣(9 折)+ 满 1500 减 200
        shared_ptr<OrderComponent> couponOrder = make_shared<CouponDecorator>(basicOrder.get(), 300.0f);
        shared_ptr<OrderComponent> discountOrder = make_shared<DiscountDecorator>(couponOrder.get(), [](float basePrice) { return basePrice * 0.9f; });
        shared_ptr<OrderComponent> fullReduceOrder = make_shared<FullReduceDecorator>(discountOrder.get(), 1500.0f, 200.0f);

        cout << "=== 智能指针管理:多层优惠组合 ===" << endl;
        cout << fullReduceOrder->GetOrderDescription() << endl;
        cout << "最终价格:" << fullReduceOrder->CalculateFinalPrice() << "元" << endl;

        // 智能指针自动析构,无需手动 delete
    } catch (const exception& e) {
        cout << "错误:" << e.what() << endl;
    }
    return 0;
}
优化 2:新增'限时折扣'装饰者(支持动态折扣率)
// 具体装饰者 4:限时折扣(支持动态设置折扣率)
class TimeLimitDiscountDecorator : public DiscountDecorator {
private:
    float discountRate; // 折扣率(如 0.9 表示 9 折)

public:
    TimeLimitDiscountDecorator(OrderComponent* comp, float rate) : DiscountDecorator(comp), discountRate(rate) {
        if (rate <= 0 || rate >= 1) {
            throw invalid_argument("折扣率必须在 (0,1) 之间!");
        }
    }

    // 计算最终价格:基础价格 * 折扣率
    float CalculateFinalPrice() const override {
        float basePrice = GetComponent()->CalculateFinalPrice();
        return basePrice * discountRate;
    }

    string GetOrderDescription() const override {
        return GetComponent()->GetOrderDescription() + " + 限时" + to_string(discountRate * 10) + "折";
    }

    // 动态修改折扣率(扩展功能)
    void SetDiscountRate(float rate) {
        if (rate <= 0 || rate >= 1) {
            throw invalid_argument("折扣率必须在 (0,1) 之间!");
        }
        discountRate = rate;
    }
};

// 客户端测试动态折扣
int main() {
    shared_ptr<OrderComponent> basicOrder = make_shared<BasicOrder>("ORD20240502003", 1000.0f);
    shared_ptr<TimeLimitDiscountDecorator> timeLimitOrder = make_shared<TimeLimitDiscountDecorator>(basicOrder.get(), 0.9f);
    cout << "=== 限时折扣测试 ===" << endl;
    cout << timeLimitOrder->GetOrderDescription() << endl;
    cout << "9 折后价格:" << timeLimitOrder->CalculateFinalPrice() << "元" << endl;

    // 动态修改为 8 折
    timeLimitOrder->SetDiscountRate(0.8f);
    cout << "\n修改为 8 折后:" << endl;
    cout << timeLimitOrder->GetOrderDescription() << endl;
    cout << "8 折后价格:" << timeLimitOrder->CalculateFinalPrice() << "元" << endl;
    return 0;
}
优化后运行结果
=== 限时折扣测试 === 订单 [ORD20240502003] 基础价格:1000.000000 元 + 限时 9.000000 折 9 折后价格:900 元
修改为 8 折后:订单 [ORD20240502003] 基础价格:1000.000000 元 + 限时 8.000000 折 8 折后价格:800 元
装饰者模式的优缺点与避坑指南
优点
  • 动态扩展功能:无需修改原有代码,通过新增装饰者即可扩展功能,符合开放 - 封闭原则;
  • 功能组合灵活:多个装饰者可嵌套组合,实现复杂功能(如优惠券 + 积分 + 满减);
  • 替代继承减少类爆炸:避免为每个功能组合创建单独的子类;
  • 保持接口一致性:装饰者与被装饰者继承自同一抽象接口,可无缝替换。
缺点
  • 层级嵌套复杂:多层装饰者嵌套后,调试和理解难度增加;
  • 内存管理复杂:手动管理时需按层级释放资源,容易出现内存泄漏或重复释放;
  • 仅适用于同一抽象接口:装饰者与被装饰者必须依赖同一抽象组件,否则无法装饰。
避坑指南
  • 使用智能指针管理内存:优先使用 shared_ptr 自动管理装饰者和被装饰对象的生命周期,避免手动释放错误;
  • 控制装饰者层级:避免过度嵌套(建议不超过 3 层),复杂组合可通过'复合装饰者'简化;
  • 明确装饰顺序:不同装饰顺序可能导致结果不同,需在业务中明确规则;
  • 抽象组件接口简洁:抽象组件只定义核心接口,避免冗余方法,降低装饰者实现成本。

适配器模式:接口兼容的桥梁方案

适配器模式(Adapter Pattern)的核心思想是'将一个类的接口转换成客户希望的另一个接口,使原本由于接口不兼容而不能一起工作的那些类可以一起工作'。

核心角色与实现方式
1. 核心角色
  • 目标接口(Target):客户期望的接口,适配器将其他接口转换为该接口;
  • 适配者(Adaptee):现有需要适配的接口(如第三方库接口、旧系统接口);
  • 适配器(Adapter):实现目标接口,同时持有适配者的引用(或继承适配者),将目标接口的调用转换为适配者接口的调用。
2. 两种实现方式
  • 类适配器:适配器继承自适配者和目标接口(多重继承),通过继承获取适配者的功能,实现目标接口供客户端调用;
  • 对象适配器:适配器实现目标接口,同时持有适配者的对象引用(组合方式),通过委托调用适配者的功能。

实战建议: C++ 中优先使用对象适配器,避免多重继承带来的菱形继承、二义性等问题,且组合方式更灵活,支持适配多个适配者。

适用场景
  • 集成第三方库:第三方库的接口与项目现有接口不匹配,需适配后使用;
  • 旧系统改造:旧系统的接口无法修改,但新系统需要使用其功能;
  • 接口标准化:多个类的功能相同但接口不同,需统一为目标接口;
  • 复用现有类:现有类功能满足需求,但接口不符合客户端要求。
实现方式 1:对象适配器(推荐)

以'第三方支付接口适配'为例:项目现有支付接口(目标接口)要求 Pay(float amount) 方法,而引入的第三方支付库(适配者)的接口为 DoPayment(float money, string orderId),使用对象适配器将第三方接口转换为项目所需接口。

步骤 1:定义目标接口(项目现有支付接口)
#include <iostream>
#include <string>
using namespace std;

// 目标接口:项目现有支付接口
class PaymentTarget {
public:
    virtual bool Pay(float amount) = 0;       // 客户期望的接口:支付指定金额
    virtual string GetPaymentName() const = 0; // 获取支付方式名称
    virtual ~PaymentTarget() {}
};
步骤 2:定义适配者(第三方支付库接口)
// 适配者:第三方支付库(接口与目标接口不兼容)
class ThirdPartyPayment {
public:
    // 第三方接口:支付金额 + 订单 ID,返回是否成功
    bool DoPayment(float money, const string& orderId) {
        cout << "第三方支付库执行支付:订单 ID=" << orderId << ",金额=" << money << "元" << endl;
        // 模拟支付成功
        return true;
    }

    // 第三方额外功能:查询支付状态
    string QueryPaymentStatus(const string& orderId) {
        return "订单" + orderId + "支付成功";
    }
};
步骤 3:实现对象适配器(转换接口)
// 对象适配器:将第三方支付接口转换为目标接口
class PaymentAdapter : public PaymentTarget {
private:
    ThirdPartyPayment* adaptee; // 持有适配者的引用(组合方式)
    string orderId;             // 订单 ID(适配时需要)

public:
    // 构造函数:传入适配者和订单 ID
    PaymentAdapter(ThirdPartyPayment* adapteeObj, const string& id) : adaptee(adapteeObj), orderId(id) {
        if (adapteeObj == nullptr) {
            throw invalid_argument("适配者对象不能为空!");
        }
    }

    ~PaymentAdapter() {
        // 适配器不负责销毁适配者(由客户端管理)
    }

    // 实现目标接口:将 Pay 调用转换为 DoPayment 调用
    bool Pay(float amount) override {
        if (amount <= 0) {
            cout << "支付金额必须大于 0!" << endl;
            return false;
        }
        // 委托适配者执行支付
        return adaptee->DoPayment(amount, orderId);
    }

    string GetPaymentName() const override {
        return "第三方支付(适配器转换)";
    }

    // 扩展功能:通过适配器调用适配者的额外方法
    string QueryStatus() {
        return adaptee->QueryPaymentStatus(orderId);
    }
};
步骤 4:客户端使用示例
// 客户端代码:只依赖目标接口,不关心具体实现
void ProcessPayment(PaymentTarget* payment, float amount) {
    cout << "=== 执行支付 ===" << endl;
    cout << "支付方式:" << payment->GetPaymentName() << endl;
    bool success = payment->Pay(amount);
    if (success) {
        cout << "支付成功!" << endl;
    } else {
        cout << "支付失败!" << endl;
    }
}

int main() {
    try {
        // 1. 创建适配者(第三方支付库)
        ThirdPartyPayment* thirdPartyPay = new ThirdPartyPayment();

        // 2. 创建适配器(传入适配者和订单 ID)
        PaymentAdapter* adapter = new PaymentAdapter(thirdPartyPay, "ORD20240503001");

        // 3. 客户端通过目标接口调用(无需知道第三方接口细节)
        ProcessPayment(adapter, 899.0f);

        // 4. 调用适配器扩展的查询功能
        cout << "\n查询支付状态:" << adapter->QueryStatus() << endl;

        // 5. 释放资源
        delete adapter;
        delete thirdPartyPay;
    } catch (const exception& e) {
        cout << "错误:" << e.what() << endl;
    }
    return 0;
}
运行结果
=== 执行支付 === 支付方式:第三方支付(适配器转换) 第三方支付库执行支付:订单 ID=ORD20240503001,金额=899 元 支付成功! 查询支付状态:订单 ORD20240503001 支付成功
实现方式 2:类适配器(多重继承)

同样以'第三方支付接口适配'为例,使用类适配器实现(继承适配者和目标接口):

步骤 1-2:目标接口和适配者与对象适配器一致
步骤 3:实现类适配器
// 类适配器:继承适配者和目标接口(多重继承)
class PaymentClassAdapter : public PaymentTarget, public ThirdPartyPayment {
private:
    string orderId;

public:
    PaymentClassAdapter(const string& id) : orderId(id) {}

    // 实现目标接口:调用父类(适配者)的 DoPayment 方法
    bool Pay(float amount) override {
        if (amount <= 0) {
            cout << "支付金额必须大于 0!" << endl;
            return false;
        }
        // 直接调用继承自 ThirdPartyPayment 的 DoPayment 方法
        return DoPayment(amount, orderId);
    }

    string GetPaymentName() const override {
        return "第三方支付(类适配器)";
    }

    // 扩展功能:调用继承的 QueryPaymentStatus 方法
    string QueryStatus() {
        return QueryPaymentStatus(orderId);
    }
};
步骤 4:客户端使用示例
int main() {
    // 类适配器无需创建适配者对象,直接使用适配器
    PaymentClassAdapter* classAdapter = new PaymentClassAdapter("ORD20240503002");
    ProcessPayment(classAdapter, 1299.0f);
    cout << "\n查询支付状态:" << classAdapter->QueryStatus() << endl;
    delete classAdapter;
    return 0;
}
运行结果
=== 执行支付 === 支付方式:第三方支付(类适配器) 第三方支付库执行支付:订单 ID=ORD20240503002,金额=1299 元 支付成功! 查询支付状态:订单 ORD20240503002 支付成功
两种适配器实现的对比
对比维度类适配器对象适配器
实现方式多重继承(目标接口 + 适配者)组合(实现目标接口 + 持有适配者引用)
灵活性差:只能适配特定适配者,无法适配其子类好:可适配适配者及其子类,支持多个适配者
耦合度高:与适配者类强耦合低:与适配者接口弱耦合
扩展能力差:新增适配者需修改或新增适配器好:可通过构造函数传入不同适配者
访问适配者方法直接访问(继承)间接访问(委托)
适用场景适配者类稳定,无子类扩展适配者可能有子类,需灵活适配

实战结论: 对象适配器在灵活性、低耦合度上优势明显,是 C++ 开发中的首选方案;类适配器仅适用于适配者类稳定、无扩展需求的简单场景。

适配器模式的优缺点与避坑指南
优点
  • 解决接口不兼容问题:使原本无法协作的类可以一起工作(如第三方库与项目接口);
  • 复用现有功能:无需修改现有类(适配者)的代码,直接复用其功能;
  • 透明性:客户端只依赖目标接口,无需知道适配者的存在,降低代码耦合;
  • 灵活性高:对象适配器支持适配多个适配者,可动态切换适配者。
缺点
  • 增加系统复杂度:新增适配器类会增加代码量,降低系统可读性;
  • 适配逻辑复杂:若目标接口与适配者接口差异较大,适配器的转换逻辑会非常复杂;
  • 性能损耗:适配器的委托调用会带来轻微的性能损耗(可忽略不计)。
避坑指南
  • 明确适配边界:适配器只负责接口转换,不添加额外业务逻辑(避免适配器职责过重);
  • 避免过度适配:若目标接口与适配者接口差异过大(如需要大量转换逻辑),应考虑重构接口,而非使用适配器;
  • 优先适配接口而非实现:适配器依赖适配者的接口,而非具体实现,确保适配者替换时适配器仍可用;
  • 结合工厂模式:使用工厂模式创建适配器,客户端无需关心适配器的创建细节,提升代码可维护性。

实战案例:结合装饰者模式与适配器模式开发支付网关系统

需求分析

开发一个统一支付网关系统,核心需求如下:

  1. 支持多种支付方式(微信支付、支付宝支付、第三方支付库),且支付接口统一(目标接口 Pay(float amount));
  2. 支付过程需动态添加额外功能(如日志记录、签名验证、支付结果回调);
  3. 第三方支付库的接口与统一接口不兼容,需适配后使用;
  4. 支持支付方式和额外功能的灵活扩展(如新增银联支付、新增风控校验功能);
  5. 客户端只需调用统一接口,无需关心具体支付方式和扩展功能的实现。
设计思路
  • 适配器模式:将第三方支付库、微信支付、支付宝支付的接口适配为统一支付接口(PaymentTarget);
  • 装饰者模式:为统一支付接口动态添加日志记录、签名验证、回调通知等扩展功能;
  • 组合设计:适配器封装具体支付方式的接口,装饰者包裹适配器(或基础支付类),实现'接口统一 + 功能扩展'的双重目标。
完整实现代码
#include <iostream>
#include <string>
#include <memory>
#include <ctime>
using namespace std;

// -------------------------- 部分 1:目标接口与基础支付类 --------------------------
// 目标接口:统一支付接口
class PaymentTarget {
public:
    virtual bool Pay(float amount) = 0;
    virtual string GetPaymentName() const = 0;
    virtual ~PaymentTarget() {}
};

// 基础支付类 1:微信支付(已符合目标接口,无需适配)
class WeChatPayment : public PaymentTarget {
public:
    bool Pay(float amount) override {
        cout << "[微信支付] 发起支付请求,金额:" << amount << "元" << endl;
        // 模拟支付流程
        return true;
    }
    string GetPaymentName() const override {
        return "微信支付";
    }
};

// 基础支付类 2:支付宝支付(已符合目标接口,无需适配)
class AlipayPayment : public PaymentTarget {
public:
    bool Pay(float amount) override {
        cout << "[支付宝支付] 发起支付请求,金额:" << amount << "元" << endl;
        return true;
    }
    string GetPaymentName() const override {
        return "支付宝支付";
    }
};

// -------------------------- 部分 2:适配器模式 - 第三方支付适配 --------------------------
// 适配者:第三方支付库(接口不兼容)
class ThirdPartyPayLib {
public:
    bool ExecutePay(const string& orderNo, double money, const string& token) {
        cout << "[第三方支付库] 订单号:" << orderNo << ",金额:" << money << "元,token:" << token << endl;
        return true;
    }
    string GetPayResult(const string& orderNo) {
        return "第三方支付成功,订单号:" + orderNo;
    }
};

// 对象适配器:第三方支付适配为统一接口
class ThirdPartyPayAdapter : public PaymentTarget {
private:
    shared_ptr<ThirdPartyPayLib> adaptee;
    string orderNo;
    string token;

public:
    ThirdPartyPayAdapter(const string& no, const string& tk) : orderNo(no), token(tk) {
        adaptee = make_shared<ThirdPartyPayLib>();
    }

    bool Pay(float amount) override {
        if (amount <= 0) return false;
        // 转换参数并委托适配者执行支付
        return adaptee->ExecutePay(orderNo, amount, token);
    }

    string GetPaymentName() const override {
        return "第三方支付(适配器)";
    }

    string QueryPayResult() {
        return adaptee->GetPayResult(orderNo);
    }
};

// -------------------------- 部分 3:装饰者模式 - 支付功能扩展 --------------------------
// 抽象装饰者:支付功能装饰器
class PaymentDecorator : public PaymentTarget {
private:
    shared_ptr<PaymentTarget> component;

protected:
    shared_ptr<PaymentTarget> GetComponent() const {
        return component;
    }

public:
    PaymentDecorator(shared_ptr<PaymentTarget> comp) : component(comp) {
        if (!component) throw invalid_argument("支付组件不能为空!");
    }

    bool Pay(float amount) override {
        return component->Pay(amount);
    }

    string GetPaymentName() const override {
        return component->GetPaymentName();
    }
};

// 具体装饰者 1:日志记录装饰器(记录支付时间和金额)
class LogPaymentDecorator : public PaymentDecorator {
public:
    LogPaymentDecorator(shared_ptr<PaymentTarget> comp) : PaymentDecorator(comp) {}

    bool Pay(float amount) override {
        // 前置日志:记录支付开始时间
        time_t now = time(nullptr);
        cout << "[支付日志] " << ctime(&now) << " 开始支付,方式:" << GetComponent()->GetPaymentName() << ",金额:" << amount << "元" << endl;

        // 调用被装饰对象的支付方法
        bool success = GetComponent()->Pay(amount);

        // 后置日志:记录支付结果
        cout << "[支付日志] 支付结果:" << (success ? "成功" : "失败") << endl;
        return success;
    }

    string GetPaymentName() const override {
        return GetComponent()->GetPaymentName() + "(带日志)";
    }
};

// 具体装饰者 2:签名验证装饰器(支付前验证签名)
class SignaturePaymentDecorator : public PaymentDecorator {
private:
    string appSecret;

public:
    SignaturePaymentDecorator(shared_ptr<PaymentTarget> comp, const string& secret) : PaymentDecorator(comp), appSecret(secret) {}

    bool Pay(float amount) override {
        // 前置功能:签名验证
        cout << "[签名验证] 正在验证签名,appSecret:" << appSecret << endl;
        bool verifySuccess = true; // 模拟签名验证成功
        if (!verifySuccess) {
            cout << "[签名验证] 签名失败,支付终止!" << endl;
            return false;
        }
        cout << "[签名验证] 签名成功,继续支付..." << endl;

        // 调用支付方法
        return GetComponent()->Pay(amount);
    }

    string GetPaymentName() const override {
        return GetComponent()->GetPaymentName() + "(带签名验证)";
    }
};

// 具体装饰者 3:回调通知装饰器(支付后发送回调)
class CallbackPaymentDecorator : public PaymentDecorator {
private:
    string callbackUrl;

public:
    CallbackPaymentDecorator(shared_ptr<PaymentTarget> comp, const string& url) : PaymentDecorator(comp), callbackUrl(url) {}

    bool Pay(float amount) override {
        // 先执行支付
        bool success = GetComponent()->Pay(amount);

        // 后置功能:发送回调
        if (success) {
            cout << "[回调通知] 向" << callbackUrl << "发送支付成功回调" << endl;
        } else {
            cout << "[回调通知] 向" << callbackUrl << "发送支付失败回调" << endl;
        }
        return success;
    }

    string GetPaymentName() const override {
        return GetComponent()->GetPaymentName() + "(带回调)";
    }
};

// -------------------------- 部分 4:客户端测试与系统整合 --------------------------
// 支付网关:统一调度类(简化客户端使用)
class PaymentGateway {
public:
    static bool ProcessPayment(shared_ptr<PaymentTarget> payment, float amount) {
        cout << "\n==================== 支付网关 ====================" << endl;
        cout << "支付方式:" << payment->GetPaymentName() << endl;
        cout << "支付金额:" << amount << "元" << endl;
        bool success = payment->Pay(amount);
        cout << "==================================================" << endl;
        return success;
    }
};

int main() {
    try {
        // 1. 微信支付 + 日志 + 签名验证 + 回调
        shared_ptr<PaymentTarget> wechatPay = make_shared<WeChatPayment>();
        wechatPay = make_shared<LogPaymentDecorator>(wechatPay);
        wechatPay = make_shared<SignaturePaymentDecorator>(wechatPay, "wechat_secret_123");
        wechatPay = make_shared<CallbackPaymentDecorator>(wechatPay, "https://api.example.com/wechat/callback");
        PaymentGateway::ProcessPayment(wechatPay, 699.0f);

        // 2. 第三方支付(适配器)+ 日志 + 回调
        shared_ptr<PaymentTarget> thirdPartyPay = make_shared<ThirdPartyPayAdapter>("ORDER_20240504_001", "token_abc123");
        thirdPartyPay = make_shared<LogPaymentDecorator>(thirdPartyPay);
        thirdPartyPay = make_shared<CallbackPaymentDecorator>(thirdPartyPay, "https://api.example.com/thirdparty/callback");
        PaymentGateway::ProcessPayment(thirdPartyPay, 1599.0f);

        // 3. 支付宝支付(无扩展功能)
        shared_ptr<PaymentTarget> alipay = make_shared<AlipayPayment>();
        PaymentGateway::ProcessPayment(alipay, 399.0f);

        // 4. 扩展:新增银联支付(只需实现 PaymentTarget 接口,无需修改现有代码)
        class UnionPayPayment : public PaymentTarget {
        public:
            bool Pay(float amount) override {
                cout << "[银联支付] 发起支付请求,金额:" << amount << "元" << endl;
                return true;
            }
            string GetPaymentName() const override {
                return "银联支付";
            }
        };
        shared_ptr<PaymentTarget> unionPay = make_shared<UnionPayPayment>();
        unionPay = make_shared<LogPaymentDecorator>(unionPay);
        PaymentGateway::ProcessPayment(unionPay, 899.0f);
    } catch (const exception& e) {
        cout << "支付网关错误:" << e.what() << endl;
    }
    return 0;
}
代码说明与运行效果
核心设计亮点
  • 适配器模式解决接口兼容:第三方支付库通过适配器转换为统一支付接口,与微信支付、支付宝支付无缝集成;
  • 装饰者模式实现功能扩展:日志、签名、回调等功能通过装饰者动态添加,支持灵活组合(如'日志 + 签名''日志 + 回调');
  • 客户端无感知:支付网关提供统一接口,客户端无需关心具体支付方式和扩展功能的实现,只需传入封装后的支付对象;
  • 扩展性强:新增支付方式只需实现 PaymentTarget 接口,新增扩展功能只需新增装饰者类,无需修改现有核心代码。
运行结果(关键片段)
==================== 支付网关 ==================== 支付方式:微信支付(带日志)(带签名验证)(带回调) 支付金额:699 元 [支付日志] Wed May 4 10:00:00 2024 开始支付,方式:微信支付(带签名验证)(带回调),金额:699 元 [签名验证] 正在验证签名,appSecret:wechat_secret_123 [签名验证] 签名成功,继续支付... [微信支付] 发起支付请求,金额:699 元 [回调通知] 向 https://api.example.com/wechat/callback 发送支付成功回调 [支付日志] 支付结果:成功 ================================================== ==================== 支付网关 ==================== 支付方式:第三方支付(适配器)(带日志)(带回调) 支付金额:1599 元 [支付日志] Wed May 4 10:00:00 2024 开始支付,方式:第三方支付(适配器)(带回调),金额:1599 元 [第三方支付库] 订单号:ORDER_20240504_001,金额:1599 元,token:token_abc123 [回调通知] 向 https://api.example.com/thirdparty/callback 发送支付成功回调 [支付日志] 支付结果:成功 ================================================== ==================== 支付网关 ==================== 支付方式:支付宝支付 支付金额:399 元 [支付宝支付] 发起支付请求,金额:399 元 ================================================== ==================== 支付网关 ==================== 支付方式:银联支付(带日志) 支付金额:899 元 [支付日志] Wed May 4 10:00:00 2024 开始支付,方式:银联支付,金额:899 元 [银联支付] 发起支付请求,金额:899 元 [支付日志] 支付结果:成功 ==================================================

本章总结

本章重点讲解了 C++ 开发中常用的两种结构型设计模式:装饰者模式和适配器模式,核心要点总结如下:

  1. 装饰者模式:
    • 核心价值:动态扩展对象功能,避免继承导致的类爆炸;
    • 关键实现:抽象组件定义统一接口,抽象装饰者持有组件引用,具体装饰者添加额外功能;
    • 核心优势:功能组合灵活、符合开放 - 封闭原则、保持接口一致性;
    • 适用场景:动态添加/移除功能、功能组合多样、不修改原有代码扩展功能。
  2. 适配器模式:
    • 核心价值:解决接口不兼容问题,使不同接口的类可以协同工作;
    • 两种实现:对象适配器(组合方式,推荐)、类适配器(多重继承,慎用);
    • 核心优势:复用现有功能、透明适配、低耦合、灵活性高;
    • 适用场景:集成第三方库、旧系统改造、接口标准化、复用现有类。
  3. 模式组合技巧:
    • 装饰者 + 适配器:适配器统一接口,装饰者扩展功能(如支付网关案例);
    • 装饰者 + 工厂模式:工厂创建基础组件,装饰者动态添加功能,简化客户端使用;
    • 适配器 + 策略模式:适配器适配不同接口的策略,策略模式动态切换算法。
  4. 实战注意事项:
    • 装饰者模式:控制装饰层级、使用智能指针管理内存、明确装饰顺序;
    • 适配器模式:避免过度适配、只负责接口转换不添加业务逻辑、优先使用对象适配器;
    • 通用原则:优先组合而非继承、符合开放 - 封闭原则、接口简洁化、避免过度设计。

通过本章学习,你应能熟练运用装饰者模式和适配器模式解决实际开发中的'功能扩展'和'接口兼容'问题,结合两种模式的组合使用,编写灵活、可扩展、低耦合的 C++ 代码。后续章节将继续讲解其他结构型设计模式(如代理模式、组合模式),进一步完善你的设计模式知识体系。

目录

  1. 设计模式实战:C++ 中装饰者模式与适配器模式的应用
  2. 本章学习目标与重点
  3. 设计模式进阶认知:结构型模式的核心价值
  4. 为什么需要结构型设计模式?
  5. 结构型模式的核心设计原则
  6. 装饰者模式:动态扩展对象功能的灵活方案
  7. 核心角色与设计逻辑
  8. 1. 核心角色
  9. 2. 设计逻辑
  10. 适用场景
  11. 基础实现:电商订单优惠系统(C++ 示例)
  12. 步骤 1:定义抽象组件(订单接口)
  13. 步骤 2:实现具体组件(基础订单)
  14. 步骤 3:定义抽象装饰者(优惠装饰器接口)
  15. 步骤 4:实现具体装饰者(各种优惠)
  16. 步骤 5:客户端使用示例(灵活组合优惠)
  17. 运行结果
  18. 进阶优化:智能指针管理与多层装饰增强
  19. 优化 1:使用智能指针管理内存
  20. 优化 2:新增“限时折扣”装饰者(支持动态折扣率)
  21. 优化后运行结果
  22. 装饰者模式的优缺点与避坑指南
  23. 优点
  24. 缺点
  25. 避坑指南
  26. 适配器模式:接口兼容的桥梁方案
  27. 核心角色与实现方式
  28. 1. 核心角色
  29. 2. 两种实现方式
  30. 适用场景
  31. 实现方式 1:对象适配器(推荐)
  32. 步骤 1:定义目标接口(项目现有支付接口)
  33. 步骤 2:定义适配者(第三方支付库接口)
  34. 步骤 3:实现对象适配器(转换接口)
  35. 步骤 4:客户端使用示例
  36. 运行结果
  37. 实现方式 2:类适配器(多重继承)
  38. 步骤 1-2:目标接口和适配者与对象适配器一致
  39. 步骤 3:实现类适配器
  40. 步骤 4:客户端使用示例
  41. 运行结果
  42. 两种适配器实现的对比
  43. 适配器模式的优缺点与避坑指南
  44. 优点
  45. 缺点
  46. 避坑指南
  47. 实战案例:结合装饰者模式与适配器模式开发支付网关系统
  48. 需求分析
  49. 设计思路
  50. 完整实现代码
  51. 代码说明与运行效果
  52. 核心设计亮点
  53. 运行结果(关键片段)
  54. 本章总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • ChatGPT 降低 AIGC 率指令实战:从原理到最佳实践
  • Python 打包编译工具 PyInstaller 与 Nuitka 特性对比
  • 大模型核心面试题与关键技术解析
  • Linux 进程创建与终止:fork 原理与退出机制实战
  • Qwen3-14B 本地部署与 Ollama WebUI 集成实战
  • VS Code 远程连接服务器后 GitHub Copilot 无法使用修复方案
  • C++ vector 容器使用、迭代器失效与模拟实现
  • ROS2 slam_toolbox 激光雷达建图教程
  • Stable Diffusion 底模与 VAE 搭配指南:提升生成质量的核心策略
  • Mac 上 Maven 安装与环境变量配置指南
  • 鸿蒙金融理财全栈项目:风险控制、合规审计与产品创新
  • ClawX 可视化 AI 智能体工具介绍与使用指南
  • Obsidian 集成 AI 插件实现笔记自动化与可视化生成
  • AI 编程实战:Superpowers Skills 与 OpenSpec 协同指南
  • 飞书机器人集成 Claude Code 实现移动端 AI 编程交互
  • 快速构建适配 imToken DApp 浏览器的区块链猜数字游戏
  • 2026 年 AI 辅助编程工具对比:Copilot、Cursor、Claude Code 与 Codex
  • OpenClaw Self-Improving 技能解析:从 SKILL.md 看 AI 自我进化逻辑
  • 医疗 AI 场景下的朴素贝叶斯算法深度解析与实战
  • 2026 年 AI 编程工具全景评测与选型指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online