(二)结构型模式:5、装饰器模式(Decorator Pattern)(C++实例)

目录

1、装饰器模式(Decorator Pattern)含义

2、装饰器模式的UML图学习

3、装饰器模式的应用场景

4、装饰器模式的优缺点

5、C++实现装饰器模式的简单实例


1、装饰器模式(Decorator Pattern)含义

装饰模式(Decorator),动态地给一个对象添加一些额外地职责,就增加功能来说,装饰模式比生成子类更为灵活【DP】

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许你在不改变现有对象结构的情况下,动态地向对象添加额外的功能。

装饰模式通过将对象包装在装饰器类中,实现了透明地扩展对象的能力。

2、装饰器模式的UML图学习

 组成元素:

(1)Component是定义一个对象接口,可以给这些对象动态地添加职责;

(2)ConcreteComponent是定义了一个具体地对象,也可以给这个对象添加一些职责;

(3)Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能【DPE】

3、装饰器模式的应用场景

(1)IO流操作:在IO流中,可以使用装饰器模式来添加缓冲、加密、压缩等功能,而无需修改原始的IO类。

(2)GUI组件:在图形用户界面中,可以使用装饰器模式来为组件添加边框、滚动条、阴影等外观效果。

(3)日志记录:可以使用装饰器模式来为日志记录器添加时间戳、日志级别等额外信息。

(4)权限控制:可以使用装饰器模式来为对象添加权限验证、身份认证等功能。

总之,装饰器模式适用于需要动态地为对象添加功能,并且希望保持对象接口的一致性的场景。

它提供了一种灵活、可扩展和可维护的方式来处理对象功能的变化和组合。

4、装饰器模式的优缺点

(1)优点:

1)动态地为对象添加功能:装饰器模式允许在运行时动态地为对象添加额外的功能,而无需修改原始对象的结构。这对于需要灵活地扩展对象功能的情况非常有用。

2)避免使用子类进行扩展:通过使用装饰器模式,可以避免创建大量的子类来实现不同组合的功能。相反,可以通过组合和堆叠装饰器来实现各种功能组合,从而更好地管理和维护代码。

3)对象功能的透明性:装饰器模式使得客户端可以透明地使用被装饰对象和装饰后的对象,无需关心具体对象的类型。这样可以简化客户端代码,并且使得代码更加清晰易懂。

4)单一职责原则:装饰器模式可以将功能划分到不同的装饰器中,每个装饰器只负责一个特定的功能,符合单一职责原则。这样可以使得代码更加可维护和可扩展。

(2)缺点:

1)增加复杂性:使用装饰器模式会引入更多的类和对象,从而增加了系统的设计复杂性。这可能会导致代码结构变得复杂,不易理解和维护。

2)多层装饰影响性能:当使用多个装饰器进行功能堆叠时,可能会对性能产生一定的影响。每个装饰器都会增加额外的处理逻辑,可能会导致性能下降。

3)可能造成对象过度膨胀:如果使用过多的装饰器或者装饰器的组合方式不合理,可能会导致对象过度膨胀,使得系统资源消耗增加。

总结:尽管装饰器模式存在一些缺点,但它仍然是一种强大且常用的设计模式,特别适用于需要动态地为对象添加功能的场景。

在使用装饰器模式时,需要根据具体的需求和系统设计来权衡其优缺点,并确保合理地应用该模式。

5、C++实现装饰器模式的简单实例

#include <iostream>// 抽象组件
class Component 
{
public:virtual void operation() const = 0;
};// 具体组件
class ConcreteComponent : public Component 
{
public:void operation() const override {std::cout << "ConcreteComponent operation" << std::endl;}
};// 抽象装饰器
class Decorator : public Component 
{
protected:Component* component;public:Decorator(Component* component) : component(component) {}void operation() const override {if (component != nullptr) {component->operation();}}
};// 具体装饰器
class ConcreteDecorator : public Decorator 
{
public:ConcreteDecorator(Component* component) : Decorator(component) {}void operation() const override {Decorator::operation();additionalOperation();}void additionalOperation() const {std::cout << "Additional operation" << std::endl;}
};int main(){// 创建具体组件对象Component* component = new ConcreteComponent();// 使用具体装饰器包装具体组件对象Component* decoratedComponent = new ConcreteDecorator(component);// 调用装饰后的操作方法decoratedComponent->operation();delete decoratedComponent;delete component;return 0;
}

在上述示例中,我们定义了一个 Component 接口作为抽象组件,其中包含了一个 operation 方法。ConcreteComponent 类表示具体组件,实现了抽象组件的接口。

Decorator 类是抽象装饰器,继承自 Component,并且持有一个 Component 的引用。它通过该引用调用被装饰对象的方法。

ConcreteDecorator 类是具体装饰器,继承自 Decorator,并实现了具体的装饰逻辑。在 operation 方法中,它先调用父类的 operation 方法,然后执行额外的操作。

在 main 函数中,我们创建了一个具体组件对象 component,并使用具体装饰器 ConcreteDecorator 对其进行包装。最后,调用装饰后的操作方法 decoratedComponent->operation(),会先执行具体组件的操作方法,然后执行具体装饰器的额外操作。

运行以上代码,输出将会是:

ConcreteComponent operation

Additional operation

可以看到,通过装饰模式,我们在不改变具体组件对象的情况下,动态地为其添加了额外的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/45505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

负载均衡下的 WebShell 连接

目录 负载均衡简介负载均衡的分类网络通信分类 负载均衡下的 WebShell 连接场景描述难点介绍解决方法**Plan A** **关掉其中一台机器**&#xff08;作死&#xff09;**Plan B** **执行前先判断要不要执行****Plan C** 在Web 层做一次 HTTP 流量转发 &#xff08;重点&#xff0…

HummingBird 基于 Go 开源超轻量级 IoT 物联网平台

蜂鸟&#xff08;HummingBird&#xff09; 是 Go 语言实现的超轻量级物联网开发平台&#xff0c;包含设备接入、产品管理、物模型、告警中心、规则引擎等丰富功能模块。系统采用GoLang编写&#xff0c;占用内存极低&#xff0c; 单物理机可实现百设备的连接。 在数据存储上&…

MATLAB | 七夕节用MATLAB画个玫瑰花束叭

Hey又是一年七夕节要到了&#xff0c;每年一次直男审美MATLAB绘图大赛开始hiahiahia&#xff0c;真的这些代码越写越不知道咋写&#xff0c;又不想每年把之前的代码翻出来再发一遍&#xff0c;于是今年又对我之前写的老代码进行了点优化组合&#xff0c;整了个花球变花束&#…

人工智能大模型加速数据库存储模型发展 行列混合存储下的破局

数据存储模型 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程toadb开源库 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 在数据库的发展过程中&#xff0c;关…

MySQL5.7数据目录结构

以CentOS7为例&#xff0c;数据目录为/var/lib/mysql/&#xff0c;其内容如下&#xff1a; [rootscentos szc]# ll /var/lib/mysql/ total 122952 -rw-r----- 1 mysql mysql 56 Jan 15 16:02 auto.cnf -rw------- 1 mysql mysql 1680 Jan 15 16:02 ca-key.pem -rw-r…

系统架构设计专业技能 · 软件工程之需求工程

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…

深入浅出Pytorch函数——torch.nn.Module.apply

分类目录&#xff1a;《深入浅出Pytorch函数》总目录 相关文章&#xff1a; 深入浅出Pytorch函数——torch.nn.Module 递归地将函数fn应用于每个子模块及self&#xff0c;子模块由.children()返回。典型的用法包括初始化模型的参数&#xff08;可以参考torc.nn.init&#xff0…

Qt快速学习(一)--对象,信号和槽

目录 1.Qt概述 1.1 什么是Qt 2.2 手动创建 2.3 pro文件 2.4 一个最简单的Qt应用程序 3 第一个Qt小程序 3.1 按钮的创建 3.2 对象模型&#xff08;对象树&#xff09; 3.3 Qt窗口坐标体系 4 信号和槽机制 4.1 系统自带的信号和槽 4.2 自定义信号和槽 4.3信号槽的拓展 4…

Edge浏览器免费使用GPT3.5

搜索sider,安装Sidebar插件 注册账号即可每天免费使用30次。 Sider: ChatGPT侧边栏,GPT-4, 联网, 绘图

C++ 的关键字(保留字)完整介绍

1. asm asm (指令字符串)&#xff1a;允许在 C 程序中嵌入汇编代码。 2. auto auto&#xff08;自动&#xff0c;automatic&#xff09;是存储类型标识符&#xff0c;表明变量"自动"具有本地范围&#xff0c;块范围的变量声明&#xff08;如for循环体内的变量声明…

机器学习深度学习——NLP实战(情感分析模型——RNN实现)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——NLP实战&#xff08;情感分析模型——数据集&#xff09; &#x1f4da;订阅专栏&#xff1a;机器学习&…

非科班如何丝滑转码

文章目录 1. 引言2. 如何规划才能实现转码2.1 确定目标和动机2.2 学习路径规划2.3 寻找学习资源2.4 制定学习计划 3. 计算机岗位发展前景3.1 编程岗位3.2 数据分析和人工智能岗位3.3 网络和系统管理岗位 4. 现阶段转码的建议4.1 学习编程基础4.2 选择合适的编程语言4.3 实践和项…

Python学习笔记第六十五天(Matplotlib 绘制多图)

Python学习笔记第六十五天 Matplotlib 绘制多图subplot()subplots() 后记 Matplotlib 绘制多图 我们可以使用 pyplot 中的 subplot() 和 subplots() 方法来绘制多个子图。 subplot() 方法在绘图时需要指定位置&#xff0c;subplots() 方法可以一次生成多个&#xff0c;在调用…

re学习(34)攻防世界-csaw2013reversing2(修改汇编顺序)

参考文章&#xff1a; re学习笔记&#xff08;27&#xff09;攻防世界-re-csaw2013reversing2_Forgo7ten的博客-CSDN博客攻防世界逆向入门题之csaw2013reversing2_沐一 林的博客-CSDN博客 三种做法 1、ida静态分析修改指令 main函数反编译的代码 由于运行之后的是乱码&…

[oneAPI] 手写数字识别-BiLSTM

[oneAPI] 手写数字识别-BiLSTM 手写数字识别参数与包加载数据模型训练过程结果 oneAPI 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI&#xff1a;https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToo…

Kafka如何解决消息丢失的问题

在 Kafka 的整个架构中可以总结出消息有三次传递的过程&#xff1a; Producer 端发送消息给 Broker 端Broker 将消息进行并持久化数据Consumer 端从 Broker 将消息拉取并进行消费 在以上这三步中每一步都可能会出现丢失数据的情况&#xff0c; 那么 Kafka 到底在什么情况下才…

python rtsp 硬件解码 二

上次使用了python的opencv模块 述说了使用PyNvCodec 模块&#xff0c;这个模块本身并没有rtsp的读写&#xff0c;那么读写rtsp是可以使用很多方法的&#xff0c;我们为了输出到pytorch直接使用AI程序&#xff0c;简化rtsp 输入&#xff0c;可以直接使用ffmpeg的子进程 方法一 …

STM8遇坑[EEPROM读取debug不正常release正常][ STVP下载成功单运行不成功][定时器消抖莫名其妙的跑不通流程]

EEPROM读取debug不正常release正常 这个超级无语,研究和半天,突然发现调到release就正常了,表现为写入看起来正常读取不正常,这个无语了,不想研究了 STVP下载不能够成功运行 本文摘录于&#xff1a;https://blog.csdn.net/qlexcel/article/details/71270780只是做学习备份之…

GEEMAP 中如何拉伸图像

图像拉伸是最基础的图像增强显示处理方法&#xff0c;主要用来改善图像显示的对比度&#xff0c;地物提取流程中往往首先要对图像进行拉伸处理。图像拉伸主要有三种方式&#xff1a;线性拉伸、直方图均衡化拉伸和直方图归一化拉伸。 GEE 中使用 .sldStyle() 的方法来进行图像的…

【深入浅出C#】章节 9: C#高级主题:LINQ查询和表达式

C#高级主题涉及到更复杂、更灵活的编程概念和技术&#xff0c;能够让开发者更好地应对现代软件开发中的挑战。其中&#xff0c;LINQ查询和表达式是C#高级主题中的一项关键内容&#xff0c;具有以下重要性和优势&#xff1a; 数据处理和操作&#xff1a; 在现代软件中&#xff…