跳到主要内容C++ 设计模式实战:装饰者与适配器模式深度解析 | 极客日志C++Pay算法
C++ 设计模式实战:装饰者与适配器模式深度解析
装饰者模式与适配器模式是 C++ 结构型设计的核心。通过电商订单与支付网关案例,演示如何利用组合替代继承实现动态扩展与接口兼容。结合智能指针管理内存,提供完整可运行的代码示例,帮助开发者构建高内聚低耦合的系统架构。
虚拟内存1 浏览 C++ 设计模式实战:装饰者与适配器模式深度应用
学习目标与重点
本章旨在掌握装饰者模式的核心思想、角色划分及 C++ 实现细节,理解适配器模式的两种实现方式及其适用场景。通过结合实际业务场景(如功能增强、接口兼容),灵活运用两种模式解决类数量爆炸、接口不匹配等关键问题。
结构型模式的核心价值
在 C++ 开发中,结构型设计模式专注于解决'类与对象的组合方式'问题。相比行为型模式关注对象交互,结构型模式更侧重对象组装,通过合理的组合实现功能复用、接口兼容或功能扩展。
为什么需要结构型设计模式?
实际开发中常遇到以下结构相关的问题:
- 需为一个对象动态添加额外功能(如给商品订单添加优惠券、积分抵扣),若使用继承会导致类数量爆炸;
- 现有类的接口与目标接口不匹配(如第三方库的接口格式与项目现有接口不一致),直接使用会导致代码耦合严重;
- 类的功能过于复杂,需拆分但又不想破坏原有接口;
- 希望复用多个类的功能,但又不能通过多重继承实现(避免菱形继承、代码冗余)。
结构型模式通过标准化的组合方式,将核心功能与扩展功能分离,例如装饰者模式通过组合实现功能动态扩展,适配器模式通过转换实现接口兼容。
核心设计原则
结构型模式的设计始终围绕以下原则展开:
- 合成复用原则:优先使用对象组合,而非类继承,实现功能复用;
- 开放 - 封闭原则:扩展功能时无需修改原有代码,通过新增类实现;
- 接口隔离原则:适配或扩展时,不依赖不必要的接口,保持接口简洁;
- 依赖倒置原则:依赖抽象接口,不依赖具体实现。
装饰者模式:动态扩展对象功能的灵活方案
装饰者模式(Decorator Pattern)又称包装器模式,其核心思想是动态地给一个对象添加一些额外的职责,就像在墙上刷油漆一样,不改变对象本身的结构,却能增强其功能。
核心角色与设计逻辑
- 抽象组件:定义被装饰对象和装饰者的共同接口,是装饰者模式的基础;
- 具体组件:被装饰的核心对象,实现抽象组件接口,包含核心功能;
- 抽象装饰者:继承自抽象组件,持有一个抽象组件的引用,定义装饰者的统一接口;
- 具体装饰者:实现抽象装饰者接口,通过调用被装饰对象的方法,再添加额外功能。
抽象装饰者与具体组件继承自同一抽象组件,确保装饰者与被装饰者类型一致,可相互替换。抽象装饰者持有抽象组件的引用,通过组合方式将装饰者与被装饰者关联,实现嵌套结构,从而动态添加功能。
适用场景
- 需动态为对象添加或移除功能(如订单支付时,根据用户选择动态添加优惠券、积分抵扣等);
- 避免使用继承导致的类爆炸;
- 扩展功能需灵活组合(如商品可以同时享受折扣 + 优惠券 + 满减多重优惠);
- 不希望修改原有类的代码(符合开放 - 封闭原则)。
基础实现:电商订单优惠系统
以电商订单优惠系统为例:订单可享受多种优惠,且优惠可灵活组合。使用装饰者模式可动态扩展优惠功能。
步骤 1:定义抽象组件
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
{
:
= ;
= ;
~() {}
};
class
OrderComponent
public
virtual float CalculateFinalPrice() const
0
virtual string GetOrderDescription() const
0
virtual
OrderComponent
步骤 2:实现具体组件(基础订单)
class BasicOrder : public OrderComponent {
private:
string orderId;
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:实现具体装饰者(各种优惠)
class CouponDecorator : public DiscountDecorator {
private:
float couponAmount;
public:
CouponDecorator(OrderComponent* comp, float amount) : DiscountDecorator(comp), couponAmount(amount) {
if (amount <= 0) {
throw invalid_argument("优惠券金额必须大于 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) + "元";
}
};
class PointsDecorator : public DiscountDecorator {
private:
int points;
public:
PointsDecorator(OrderComponent* comp, int pts) : DiscountDecorator(comp), points(pts) {
if (pts <= 0) {
throw invalid_argument("抵扣积分必须大于 0!");
}
}
float CalculateFinalPrice() const override {
float basePrice = GetComponent()->CalculateFinalPrice();
float discountAmount = points / 100.0f;
float finalPrice = basePrice - discountAmount;
return finalPrice < 0 ? 0 : finalPrice;
}
string GetOrderDescription() const override {
return GetComponent()->GetOrderDescription() + " + " + to_string(points) + "积分抵扣" + to_string(points / 100.0f) + "元";
}
};
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 {
OrderComponent* basicOrder = new BasicOrder("ORD20240502001", 1500.0f);
cout << "=== 基础订单 ===" << endl;
cout << basicOrder->GetOrderDescription() << endl;
cout << "最终价格:" << basicOrder->CalculateFinalPrice() << "元" << endl;
OrderComponent* couponOrder = new CouponDecorator(basicOrder, 200.0f);
cout << "\n=== 基础订单 + 优惠券 ===" << endl;
cout << couponOrder->GetOrderDescription() << endl;
cout << "最终价格:" << couponOrder->CalculateFinalPrice() << "元" << endl;
OrderComponent* couponPointsOrder = new PointsDecorator(couponOrder, 500);
cout << "\n=== 基础订单 + 优惠券 + 积分 ===" << endl;
cout << couponPointsOrder->GetOrderDescription() << endl;
cout << "最终价格:" << couponPointsOrder->CalculateFinalPrice() << "元" << endl;
OrderComponent* fullReduceOrder = new FullReduceDecorator(couponPointsOrder, 1000.0f, 150.0f);
cout << "\n=== 基础订单 + 优惠券 + 积分 + 满减 ===" << endl;
cout << fullReduceOrder->GetOrderDescription() << endl;
cout << "最终价格:" << fullReduceOrder->CalculateFinalPrice() << "元" << endl;
OrderComponent* onlyFullReduceOrder = new FullReduceDecorator(basicOrder, 1000.0f, 150.0f);
cout << "\n=== 基础订单 + 满减 ===" << endl;
cout << onlyFullReduceOrder->GetOrderDescription() << endl;
cout << "最终价格:" << onlyFullReduceOrder->CalculateFinalPrice() << "元" << endl;
delete fullReduceOrder;
delete couponPointsOrder;
delete couponOrder;
delete onlyFullReduceOrder;
delete basicOrder;
} catch (const exception& e) {
cout << "错误:" << e.what() << endl;
}
return 0;
}
进阶优化:智能指针管理与多层装饰增强
基础实现中,手动管理装饰者层级的内存容易出错。以下优化方案使用智能指针自动管理内存,并新增限时折扣装饰者。
优化 1:使用智能指针管理内存
#include <memory>
int main() {
try {
shared_ptr<OrderComponent> basicOrder = make_shared<BasicOrder>("ORD20240502002", 2000.0f);
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;
} catch (const exception& e) {
cout << "错误:" << e.what() << endl;
}
return 0;
}
优化 2:新增限时折扣装饰者
class TimeLimitDiscountDecorator : public DiscountDecorator {
private:
float discountRate;
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;
timeLimitOrder->SetDiscountRate(0.8f);
cout << "\n修改为 8 折后:" << endl;
cout << timeLimitOrder->GetOrderDescription() << endl;
cout << "8 折后价格:" << timeLimitOrder->CalculateFinalPrice() << "元" << endl;
return 0;
}
优缺点与避坑指南
- 动态扩展功能:无需修改原有代码,通过新增装饰者即可扩展功能;
- 功能组合灵活:多个装饰者可嵌套组合,实现复杂功能;
- 替代继承减少类爆炸:避免为每个功能组合创建单独的子类;
- 保持接口一致性:装饰者与被装饰者继承自同一抽象接口,可无缝替换。
- 层级嵌套复杂:多层装饰者嵌套后,调试和理解难度增加;
- 内存管理复杂:手动管理时需按层级释放资源,容易出现内存泄漏;
- 仅适用于同一抽象接口:装饰者与被装饰者必须依赖同一抽象组件。
- 使用智能指针管理内存:优先使用
shared_ptr 自动管理生命周期;
- 控制装饰者层级:避免过度嵌套(建议不超过 3 层);
- 明确装饰顺序:不同装饰顺序可能导致结果不同,需在业务中明确规则;
- 抽象组件接口简洁:只定义核心接口,降低实现成本。
适配器模式:接口兼容的桥梁方案
适配器模式的核心思想是将一个类的接口转换成客户希望的另一个接口,使原本由于接口不兼容而不能一起工作的那些类可以一起工作。
核心角色与实现方式
- 目标接口:客户期望的接口,适配器将其他接口转换为该接口;
- 适配者:现有需要适配的接口(如第三方库接口、旧系统接口);
- 适配器:实现目标接口,同时持有适配者的引用(或继承适配者),将目标接口的调用转换为适配者接口的调用。
- 类适配器:适配器继承自适配者和目标接口(多重继承),通过继承获取适配者的功能;
- 对象适配器:适配器实现目标接口,同时持有适配者的对象引用(组合方式),通过委托调用适配者的功能。
实战建议: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:
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;
public:
PaymentAdapter(ThirdPartyPayment* adapteeObj, const string& id) : adaptee(adapteeObj), orderId(id) {
if (adapteeObj == nullptr) {
throw invalid_argument("适配者对象不能为空!");
}
}
~PaymentAdapter() {
}
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 {
ThirdPartyPayment* thirdPartyPay = new ThirdPartyPayment();
PaymentAdapter* adapter = new PaymentAdapter(thirdPartyPay, "ORD20240503001");
ProcessPayment(adapter, 899.0f);
cout << "\n查询支付状态:" << adapter->QueryStatus() << endl;
delete adapter;
delete thirdPartyPay;
} catch (const exception& e) {
cout << "错误:" << e.what() << endl;
}
return 0;
}
实现方式 2:类适配器(多重继承)
同样以第三方支付接口适配为例,使用类适配器实现(继承适配者和目标接口):
class PaymentClassAdapter : public PaymentTarget, public ThirdPartyPayment {
private:
string orderId;
public:
PaymentClassAdapter(const string& id) : orderId(id) {}
bool Pay(float amount) override {
if (amount <= 0) {
cout << "支付金额必须大于 0!" << endl;
return false;
}
return DoPayment(amount, orderId);
}
string GetPaymentName() const override {
return "第三方支付(类适配器)";
}
string QueryStatus() {
return QueryPaymentStatus(orderId);
}
};
int main() {
PaymentClassAdapter* classAdapter = new PaymentClassAdapter("ORD20240503002");
ProcessPayment(classAdapter, 1299.0f);
cout << "\n查询支付状态:" << classAdapter->QueryStatus() << endl;
delete classAdapter;
return 0;
}
两种适配器实现的对比
| 对比维度 | 类适配器 | 对象适配器 |
|---|
| 实现方式 | 多重继承(目标接口 + 适配者) | 组合(实现目标接口 + 持有适配者引用) |
| 灵活性 | 差:只能适配特定适配者,无法适配其子类 | 好:可适配适配者及其子类,支持多个适配者 |
| 耦合度 | 高:与适配者类强耦合 | 低:与适配者接口弱耦合 |
| 扩展能力 | 差:新增适配者需修改或新增适配器 | 好:可通过构造函数传入不同适配者 |
| 访问适配者方法 | 直接访问(继承) | 间接访问(委托) |
| 适用场景 | 适配者类稳定,无子类扩展 | 适配者可能有子类,需灵活适配 |
实战结论:对象适配器在灵活性、低耦合度上优势明显,是 C++ 开发中的首选方案;类适配器仅适用于适配者类稳定、无扩展需求的简单场景。
优缺点与避坑指南
- 解决接口不兼容问题:使原本无法协作的类可以一起工作;
- 复用现有功能:无需修改现有类(适配者)的代码,直接复用其功能;
- 透明性:客户端只依赖目标接口,无需知道适配者的存在,降低代码耦合;
- 灵活性高:对象适配器支持适配多个适配者,可动态切换适配者。
- 增加系统复杂度:新增适配器类会增加代码量,降低系统可读性;
- 适配逻辑复杂:若目标接口与适配者接口差异较大,适配器的转换逻辑会非常复杂;
- 性能损耗:适配器的委托调用会带来轻微的性能损耗(可忽略不计)。
- 明确适配边界:适配器只负责接口转换,不添加额外业务逻辑;
- 避免过度适配:若目标接口与适配者接口差异过大,应考虑重构接口;
- 优先适配接口而非实现:适配器依赖适配者的接口,而非具体实现;
- 结合工厂模式:使用工厂模式创建适配器,提升代码可维护性。
实战案例:结合装饰者模式与适配器模式开发支付网关系统
需求分析
- 支持多种支付方式(微信支付、支付宝支付、第三方支付库),且支付接口统一;
- 支付过程需动态添加额外功能(如日志记录、签名验证、支付结果回调);
- 第三方支付库的接口与统一接口不兼容,需适配后使用;
- 支持支付方式和额外功能的灵活扩展;
- 客户端只需调用统一接口,无需关心具体支付方式和扩展功能的实现。
设计思路
- 适配器模式:将第三方支付库、微信支付、支付宝支付的接口适配为统一支付接口;
- 装饰者模式:为统一支付接口动态添加日志记录、签名验证、回调通知等扩展功能;
- 组合设计:适配器封装具体支付方式的接口,装饰者包裹适配器(或基础支付类),实现'接口统一 + 功能扩展'的双重目标。
完整实现代码
#include <iostream>
#include <string>
#include <memory>
#include <ctime>
using namespace std;
class PaymentTarget {
public:
virtual bool Pay(float amount) = 0;
virtual string GetPaymentName() const = 0;
virtual ~PaymentTarget() {}
};
class WeChatPayment : public PaymentTarget {
public:
bool Pay(float amount) override {
cout << "[微信支付] 发起支付请求,金额:" << amount << "元" << endl;
return true;
}
string GetPaymentName() const override {
return "微信支付";
}
};
class AlipayPayment : public PaymentTarget {
public:
bool Pay(float amount) override {
cout << "[支付宝支付] 发起支付请求,金额:" << amount << "元" << endl;
return true;
}
string GetPaymentName() const override {
return "支付宝支付";
}
};
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);
}
};
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();
}
};
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() + "(带日志)";
}
};
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() + "(带签名验证)";
}
};
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() + "(带回调)";
}
};
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 {
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);
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);
shared_ptr<PaymentTarget> alipay = make_shared<AlipayPayment>();
PaymentGateway::ProcessPayment(alipay, 399.0f);
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;
}
运行效果
==================== 支付网关 ====================
支付方式:微信支付(带日志)(带签名验证)(带回调)
支付金额:699 元
[支付日志] Wed May 4 10:00:00 2024 开始支付,方式:微信支付(带签名验证)(带回调),金额:699 元
[签名验证] 正在验证签名,appSecret:wechat_secret_123
[签名验证] 签名成功,继续支付...
[微信支付] 发起支付请求,金额:699 元
[回调通知] 向 https://api.example.com/wechat/callback 发送支付成功回调
[支付日志] 支付结果:成功
==================================================
本章总结
本章重点讲解了 C++ 开发中常用的两种结构型设计模式:装饰者模式和适配器模式。
- 装饰者模式:核心价值在于动态扩展对象功能,避免继承导致的类爆炸。关键实现是抽象组件定义统一接口,抽象装饰者持有组件引用,具体装饰者添加额外功能。适用场景包括动态添加/移除功能、功能组合多样、不修改原有代码扩展功能。
- 适配器模式:核心价值是解决接口不兼容问题,使不同接口的类可以协同工作。两种实现中,对象适配器(组合方式)因灵活性和低耦合度成为首选,类适配器(多重继承)仅适用于简单场景。适用场景包括集成第三方库、旧系统改造、接口标准化。
- 模式组合技巧:装饰者 + 适配器可实现接口统一 + 功能扩展;装饰者 + 工厂模式可简化客户端使用;适配器 + 策略模式可动态切换算法。
- 实战注意事项:装饰者模式需控制层级、使用智能指针管理内存;适配器模式应避免过度适配、只负责接口转换;通用原则是优先组合而非继承、符合开放 - 封闭原则。
通过本章学习,应能熟练运用这两种模式解决实际开发中的功能扩展和接口兼容问题,编写灵活、可扩展、低耦合的 C++ 代码。后续章节将继续讲解其他结构型设计模式,进一步完善知识体系。
相关免费在线工具
- 加密/解密文本
使用加密算法(如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