当前位置: 首页 > news >正文

【C++设计模式】第五篇:装饰器模式

C++设计模式系列文章目录

【C++设计模式】第一篇 C++单例模式–懒汉与饿汉以及线程安全

【C++设计模式】第二篇:策略模式(Strategy)–从基本介绍,内部原理、应用场景、使用方法,常见问题和解决方案进行深度解析

【C++设计模式】第三篇:观察者模式(别名:发布-订阅模式、模型-视图模式、源-监听器模式)

【C++设计模式】第五篇:装饰器模式

【C++设计模式】第五篇:装饰器模式

  • C++设计模式系列文章目录
    • 一、模式核心概念与结构
    • 二、C++ 实现示例:咖啡与配料的装饰
    • 三、装饰模式与继承的对比
    • 四、应用场景
    • 五、C++ 实现注意事项
    • 六、装饰模式与其他设计模式的关系
    • 七、实战案例:网络请求处理链
    • 八、优缺点分析
    • 九、C++ 标准库中的装饰模式应用
  • C++设计模式之装饰器模式(decorator)(结构型)
  • 一、模式动机

原文链接:https://blog.csdn.net/AAADiao/article/details/148846165


装饰模式(Decorator Pattern)是一种【结构型】设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式通过创建一个装饰器类,来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。装饰模式在不使用继承的情况下,实现了对象功能的动态扩展。

一、模式核心概念与结构

装饰模式包含四个核心角色:

抽象组件(Component):定义对象的接口,可以给这些对象动态地添加职责。
具体组件(Concrete Component):实现抽象组件接口,定义具体的对象,装饰器可以给它增加额外的职责。
抽象装饰器(Decorator):继承自抽象组件,并持有一个抽象组件的引用,用于装饰具体组件。
具体装饰器(Concrete Decorator):实现抽象装饰器的方法,在调用具体组件方法的前后,添加额外的功能。

二、C++ 实现示例:咖啡与配料的装饰

以下是一个经典的装饰模式示例,演示如何动态添加咖啡的配料:

#include <iostream>
#include <string>
#include <memory>// 抽象组件:饮料
class Beverage {
public:virtual ~Beverage() {}virtual std::string getDescription() const = 0;virtual double cost() const = 0;
};// 具体组件:浓缩咖啡
class Espresso : public Beverage {
public:std::string getDescription() const override {return "Espresso";}double cost() const override {return 1.99;}
};// 具体组件:黑咖啡
class DarkRoast : public Beverage {
public:std::string getDescription() const override {return "Dark Roast Coffee";}double cost() const override {return 0.99;}
};// 抽象装饰器:配料
class CondimentDecorator : public Beverage {
protected:std::shared_ptr<Beverage> beverage;  // 持有被装饰对象的引用public:CondimentDecorator(std::shared_ptr<Beverage> b) : beverage(b) {}
};// 具体装饰器:牛奶
class Milk : public CondimentDecorator {
public:Milk(std::shared_ptr<Beverage> b) : CondimentDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Milk";}double cost() const override {return beverage->cost() + 0.30;}
};// 具体装饰器:摩卡
class Mocha : public CondimentDecorator {
public:Mocha(std::shared_ptr<Beverage> b) : CondimentDecorator(b) {}std::string getDescription() const override {return beverage->getDescription() + ", Mocha";}double cost() const override {return beverage->cost() + 0.45;}
};// 客户端代码
int main() {// 纯浓缩咖啡std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();std::cout << beverage->getDescription() << " $" << beverage->cost() << std::endl;// 加牛奶的黑咖啡std::shared_ptr<Beverage> beverage2 = std::make_shared<DarkRoast>();beverage2 = std::make_shared<Milk>(beverage2);std::cout << beverage2->getDescription() << " $" << beverage2->cost() << std::endl;// 加双份摩卡的浓缩咖啡std::shared_ptr<Beverage> beverage3 = std::make_shared<Espresso>();beverage3 = std::make_shared<Mocha>(beverage3);beverage3 = std::make_shared<Mocha>(beverage3);std::cout << beverage3->getDescription() << " $" << beverage3->cost() << std::endl;return 0;
}

三、装饰模式与继承的对比

传统继承方式的局限性:

  • 功能扩展通过创建子类实现,导致类数量爆炸。
  • 功能扩展是静态的,编译时确定,无法在运行时动态调整。

装饰模式的优势:

  • 动态组合对象功能,运行时灵活扩展。
  • 避免继承导致的类层次过深问题。
  • 符合开闭原则:无需修改原有代码,即可添加新的装饰器。

四、应用场景

  1. 动态添加功能:当需要给对象动态添加功能,且不影响其他对象时,例如:
  • 图形界面组件的边框、滚动条、阴影效果。
  • 网络请求的加密、压缩、缓存功能。
  1. 替代多重继承:当使用继承会导致类爆炸时,例如:
  • 文件流的缓冲、加密、压缩处理。
  • 游戏角色的装备、技能组合。
  1. 功能增强链:当需要按顺序执行多个功能增强时,例如:
  • 日志处理(过滤、格式化、存储)。
  • HTTP 请求处理(身份验证、参数解析、权限检查)。

五、C++ 实现注意事项

  1. 接口一致性:

装饰器必须实现与被装饰对象相同的接口(继承同一抽象类)。
确保装饰器不改变接口签名,只增强功能。
2. 智能指针管理:

// 使用智能指针避免内存泄漏
std::shared_ptr<Beverage> beverage = std::make_shared<Espresso>();
beverage = std::make_shared<Mocha>(beverage);
  1. 初始化顺序:
  • 装饰器的初始化顺序可能影响最终结果,需谨慎设计。
  1. 避免重复装饰:
  • 某些场景需防止对同一对象重复应用相同装饰器。

六、装饰模式与其他设计模式的关系

  1. 适配器模式:适配器模式详解
  • 适配器模式改变对象接口,装饰模式增强对象功能。
  • 适配器模式是 “适配”,装饰模式是 “增强”。
  1. 代理模式:
  • 代理模式控制对象访问,装饰模式增加对象功能。
  • 代理模式的重点是访问控制,装饰模式的重点是功能扩展。
  1. 建造者模式:建造者模式详解
  • 建造者模式分步构建复杂对象,装饰模式动态增强对象。
  • 建造者模式关注对象构建过程,装饰模式关注对象运行时功能。

七、实战案例:网络请求处理链

以下是一个网络请求处理链的装饰模式实现:

#include <iostream>
#include <string>
#include <memory>// 抽象组件:请求处理器
class RequestHandler {
public:virtual ~RequestHandler() {}virtual void handleRequest(const std::string& request) const = 0;
};// 具体组件:基础请求处理器
class BaseRequestHandler : public RequestHandler {
public:void handleRequest(const std::string& request) const override {std::cout << "Base handler processing request: " << request << std::endl;}
};// 抽象装饰器:请求处理器装饰器
class RequestHandlerDecorator : public RequestHandler {
protected:std::shared_ptr<RequestHandler> handler;public:RequestHandlerDecorator(std::shared_ptr<RequestHandler> h) : handler(h) {}
};// 具体装饰器:日志记录
class LoggingDecorator : public RequestHandlerDecorator {
public:LoggingDecorator(std::shared_ptr<RequestHandler> h) : RequestHandlerDecorator(h) {}void handleRequest(const std::string& request) const override {std::cout << "Logging: Request received - " << request << std::endl;handler->handleRequest(request);std::cout << "Logging: Request processed" << std::endl;}
};// 具体装饰器:权限检查
class AuthDecorator : public RequestHandlerDecorator {
public:AuthDecorator(std::shared_ptr<RequestHandler> h) : RequestHandlerDecorator(h) {}void handleRequest(const std::string& request) const override {std::cout << "Auth: Checking permissions..." << std::endl;handler->handleRequest(request);std::cout << "Auth: Permissions checked" << std::endl;}
};// 客户端代码
int main() {// 创建基础处理器std::shared_ptr<RequestHandler> baseHandler = std::make_shared<BaseRequestHandler>();// 添加日志和权限装饰std::shared_ptr<RequestHandler> authHandler = std::make_shared<AuthDecorator>(baseHandler);std::shared_ptr<RequestHandler> loggingAuthHandler = std::make_shared<LoggingDecorator>(authHandler);// 处理请求loggingAuthHandler->handleRequest("GET /api/data");return 0;
}

八、优缺点分析

优点:

  • 灵活扩展:可以在运行时动态添加或删除功能。
  • 单一职责:每个装饰器专注于一个特定功能,符合单一职责原则。
  • 开闭原则:无需修改现有代码即可添加新装饰器。

缺点:

  • 复杂性增加:多层装饰会导致系统复杂,调试困难。
  • 对象嵌套:过多装饰器可能导致对象嵌套过深,影响性能。
  • 接口一致性:装饰器必须严格遵循组件接口,否则可能破坏系统。

九、C++ 标准库中的装饰模式应用

  1. 输入 / 输出流(iostream):
  • std::basic_ios是抽象组件,std::ifstream、std::ofstream是具体组件。
  • std::ios_base::iword和std::ios_base::pword可用于动态添加流的属性。
  1. 智能指针:
  • std::shared_ptr和std::unique_ptr可视为对原始指针的装饰器,添加了内存管理功能。
  1. STL 迭代器适配器:
  • std::reverse_iterator、std::insert_iterator等是对基础迭代器的装饰。

装饰模式是 C++ 中实现对象功能动态扩展的重要工具,通过合理使用装饰器,可以构建出灵活、可维护的软件系统,同时避免继承带来的局限性。

C++设计模式之装饰器模式(decorator)(结构型)

一、模式动机

比如,给自家宠物小狗的画框需要不同的颜色等。


文章转载自:

http://puCkyezd.hxxzp.cn
http://gP9Mvwse.hxxzp.cn
http://im5ZQdHv.hxxzp.cn
http://lEaqH7V2.hxxzp.cn
http://hClxfHFD.hxxzp.cn
http://IKVuez2l.hxxzp.cn
http://b11DEaKd.hxxzp.cn
http://KfSdg4yr.hxxzp.cn
http://H4NtdUnr.hxxzp.cn
http://vrhvWoLh.hxxzp.cn
http://kEvachM0.hxxzp.cn
http://t4rCzAGd.hxxzp.cn
http://ILhMOzJO.hxxzp.cn
http://utUAAruj.hxxzp.cn
http://xKg7JM54.hxxzp.cn
http://QTjqPwSa.hxxzp.cn
http://Sl7BAbNh.hxxzp.cn
http://9efhTtDB.hxxzp.cn
http://F6zfXQMz.hxxzp.cn
http://em7o10Rj.hxxzp.cn
http://o2bOx7Os.hxxzp.cn
http://0trVCHfP.hxxzp.cn
http://cDKnTBAg.hxxzp.cn
http://aCDKVOwh.hxxzp.cn
http://vXywD2yy.hxxzp.cn
http://ilBEPusO.hxxzp.cn
http://mWZBL5Qi.hxxzp.cn
http://U68ZuguB.hxxzp.cn
http://pVLY4zbm.hxxzp.cn
http://0OwfgF0F.hxxzp.cn
http://www.dtcms.com/a/381854.html

相关文章:

  • linux C 语言开发 (十) 进程间通讯--信号
  • 绿色环保活动平台(AI问答、WebSocket即时通讯、协同过滤算法、Echarts图形化分析)
  • 飞算JavaAI实战高效构建电商系统核心功能模块全解析
  • CSS 技巧使页脚始终位于网页的底部
  • Vue3》》eslint Prettier husky
  • 基因组多组学(第七篇空间HD文章)--基于蛋白质组学的分类揭示IDH突变型星形细胞瘤中存在免疫热亚型且预后较差
  • 【无人机】无人机用户体验测试策略详细介绍
  • Bev 感知模型量化 有哪些问题
  • 深入探索React渲染原理与性能优化策略
  • 域名SSL证书免费申请lcjmSSL
  • 贪心算法应用:投资组合再平衡问题详解
  • 整体设计 之 绪 思维导图引擎 之 引 认知系统 之 引 认知系统 之 序 认知元架构 之 元宇宙:三种“即是”逻辑与数据安全措施的适配(豆包助手 之10)
  • 推荐使用 pnpm 而不是 npm
  • 19.路径
  • ESP32-C3 入门09:基于 ESP-IDF + LVGL + ST7789 的 1.54寸 WiFi 时钟(SquareLine Studio 移植)
  • 大数据毕业设计选题推荐-基于大数据的健康与生活方式数据可视化分析系统-Spark-Hadoop-Bigdata
  • 可配日志输出
  • 学习笔记:Python的起源
  • vcpkg:面向C/C++的跨平台库管理工具软件配置笔记经验教程
  • Claude Code的交互方式
  • 使用atop工具监控Linux系统指标
  • 工具链部署实用技巧 7|模型设计帧率推理时耗时与带宽分析
  • 《SRE 系列(八)| 高效组织协作经验》
  • 数据结构---链式队列
  • 【C++实战⑦】C++函数实战:从基础到项目应用
  • 通过语义AI管道检测文本数据中的潜在异常值
  • 这是第二篇
  • Mamba模型介绍
  • rock linux 9 安装mysql 5.7.44
  • 基于STM32智能农业大棚检测控制系统设计