【GeekBand】C++设计模式笔记6_Decorator_装饰模式

1. “单一职责”模式

  • 在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任
  • 典型模式
    • Decorator
    • Bridge

2. Decorator 装饰模式

2.1 动机(Motivation)

  • 在某些情况下我们可能会 “过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
  • 如何使 “对象功能的扩展” 能够根据需要来动态地实现?同时避免 “扩展功能的增多” 带来的子类膨胀问题?从而使得任何 “功能扩展变化” 所导致的影响降为最低?

2.2 模式定义

动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator 模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。
——《设计模式》GoF

2.3 实例代码

2.3.1 decorator1
// 流基类
class Stream {
public:// 纯虚函数virtual char Read(int number) = 0;virtual void Seek(int position) = 0;virtual void Write(char data) = 0;// 析构函数virtual ~Stream() {}};/******************** 主体类 ********************/
// 文件流类
class FileStream : public Stream {
public:virtual char Read(int number) {// 读文件流}virtual void Seek(int position) {// 定位文件流}virtual void Write(char data) {// 写文件流}};// 网络流类
class NetworkStream : public Stream {
public:virtual char Read(int number) {// 读网络流}virtual void Seek(int position) {// 定位网络流}virtual void Write(char data) {// 写网络流}};// 内存流类
class MemoryStream : public Stream {
public:virtual char Read(int number) {// 读内存流}virtual void Seek(int position) {// 定位内存流}virtual void Write(char data) {// 写内存流}};/******************** 扩展操作 ********************/
// 加密文件流类,继承文件流类
class CryptoFileStream : public FileStream {
public:virtual char Read(int number) { // 额外的加密操作...FileStream::Read(number);	// 读文件流,调用父类函数}virtual void Seek(int position) {// 额外的加密操作...FileStream::Seek(position);	// 定位文件流,调用父类函数// 额外的加密操作...}virtual void Write(byte data) {// 额外的加密操作...FileStream::Write(data);	// 写文件流,调用父类函数// 额外的加密操作...}
};// 加密网络流类,继承网络流类
class CryptoNetworkStream : public NetworkStream {
public:virtual char Read(int number) {  // 额外的加密操作...NetworkStream::Read(number);	// 读网络流,调用父类函数}virtual void Seek(int position) {// 额外的加密操作...NetworkStream::Seek(position);	// 定位网络流,调用父类函数// 额外的加密操作...}virtual void Write(byte data) {// 额外的加密操作...NetworkStream::Write(data);		// 写网络流,调用父类函数// 额外的加密操作...}
};// 加密内存流类,继承内存流类
class CryptoMemoryStream : public MemoryStream {
public:virtual char Read(int number) {// 额外的加密操作...MemoryStream::Read(number);		// 读内存流,调用父类函数}virtual void Seek(int position) {// 额外的加密操作...MemoryStream::Seek(position);	// 定位内存流,调用父类函数// 额外的加密操作...}virtual void Write(byte data) {// 额外的加密操作...MemoryStream::Write(data);		// 写内存流,调用父类函数// 额外的加密操作...}
};// 缓存文件流类
class BufferedFileStream : public FileStream {// ...
};// 缓存网络流类
class BufferedNetworkStream : public NetworkStream {// ...
};// 缓存内存流类
class BufferedMemoryStream : public MemoryStream {// ...
}// 加密缓存文件流类,继承文件流
class CryptoBufferedFileStream : public FileStream {
public:virtual char Read(int number) {// 额外的加密操作...// 额外的缓冲操作...FileStream::Read(number);	// 读文件流}virtual void Seek(int position) {// 额外的加密操作...// 额外的缓冲操作...FileStream::Seek(position);	// 定位文件流// 额外的加密操作...// 额外的缓冲操作...}virtual void Write(byte data) {// 额外的加密操作...// 额外的缓冲操作...FileStream::Write(data);	// 写文件流// 额外的加密操作...// 额外的缓冲操作...}
};void Process() {// 编译时装配,在编译时就确定具体的类型CryptoFileStream *fs1 = new CryptoFileStream();BufferedFileStream *fs2 = new BufferedFileStream();CryptoBufferedFileStream *fs3 = new CryptoBufferedFileStream();}
2.3.2 decorator2
// 流基类
class Stream {
public:// 纯虚函数virtual char Read(int number) = 0;virtual void Seek(int position) = 0;virtual void Write(char data) = 0;// 析构函数virtual ~Stream() {}};/******************** 主体类 ********************/
// 文件流类
class FileStream : public Stream {
public:virtual char Read(int number) {// 读文件流}virtual void Seek(int position) {// 定位文件流}virtual void Write(char data) {// 写文件流}
};// 网络流类
class NetworkStream : public Stream {
public:virtual char Read(int number) {// 读网络流}virtual void Seek(int position) {// 定位网络流}virtual void Write(char data) {// 写网络流}
};// 内存流类
class MemoryStream : public Stream {
public:virtual char Read(int number) {// 读内存流}virtual void Seek(int position) {// 定位内存流}virtual void Write(char data) {// 写内存流}
};/******************** 扩展操作 ********************/
// 加密流类
class CryptoStream : public Stream {Stream* stream;	// ...	组合形式,Stream是个抽象类,不是一个具体的类public:// 构造函数CryptoStream(Stream* stm) : stream(stm) {}virtual char Read(int number) {// 额外的加密操作...stream->Read(number);	// 读流}virtual void Seek(int position) {// 额外的加密操作...stream->Seek(position);	// 定位流// 额外的加密操作...}virtual void Write(byte data) {// 额外的加密操作...stream->Write(data);	// 写流// 额外的加密操作...}
};// 缓冲流类
class BufferedStream : public Stream {Stream* stream;	// ...	组合形式public:BufferedStream(Stream* stm) : stream(stm) {}//...
};void Process() {// 运行时装配,在运行时才确认具体类型FileStream* s1 = new FileStream();CryptoStream* s2 = new CryptoStream(s1);		// s2中的stream绑定FileStream类型BufferedStream* s3 = new BufferedStream(s1);	// s3中的stream绑定FileStream类型BufferedStream* s4 = new BufferedStream(s2);	// s4中的stream绑定CryptoStream类型
}
2.3.3 decorator3
// 流基类
class Stream {
public:// 纯虚函数virtual char Read(int number) = 0;virtual void Seek(int position) = 0;virtual void Write(char data) = 0;// 析构函数virtual ~Stream() {}
};/******************** 主体类 ********************/
// 文件流类
class FileStream: public Stream {
public:virtual char Read(int number) {// 读文件流}virtual void Seek(int position) {// 定位文件流}virtual void Write(char data) {// 写文件流}};// 网络流类
class NetworkStream : public Stream {
public:virtual char Read(int number) {// 读网络流}virtual void Seek(int position) {// 定位网络流}virtual void Write(char data) {// 写网络流}
};// 内存流类
class MemoryStream : public Stream {
public:virtual char Read(int number) {// 读内存流}virtual void Seek(int position) {// 定位内存流}virtual void Write(char data) {// 写内存流}
};/******************** 扩展操作 ********************/
// 装饰器流类
DecoratorStream : public Stream {
protected:Stream* stream;	// ...	组合形式,Stream是个抽象类,不是一个具体的类// 构造函数DecoratorStream(Stream * stm) : stream(stm) {}  
};// 加密流类,继承装饰器流类
class CryptoStream : public DecoratorStream {
public:// 构造函数,调用父类的构造函数CryptoStream(Stream* stm) : DecoratorStream(stm) {}virtual char Read(int number) {   // 额外的加密操作...stream->Read(number);	// 读流}virtual void Seek(int position) {// 额外的加密操作...stream->Seek(position);	// 定位流// 额外的加密操作...}virtual void Write(byte data) {// 额外的加密操作...stream->Write(data);	// 写流// 额外的加密操作...}
};// 缓冲流类,继承装饰器流类
class BufferedStream : public DecoratorStream {
public:// 构造函数,调用父类的构造函数BufferedStream(Stream* stm): DecoratorStream(stm) {}// ...
};void Process(){// 运行时装配FileStream* s1 = new FileStream();CryptoStream* s2 = new CryptoStream(s1);BufferedStream* s3 = new BufferedStream(s1);BufferedStream* s4 = new BufferedStream(s2);
}

2.4 结构(Structure)

在这里插入图片描述

2.5 要点总结

  • 通过采用组合而非继承的手法,Decorator 模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的 “灵活性差” 和 “多子类衍生问题”。
  • Decorator 类在接口上表现为is-a Component 的继承关系,即 Decorator 类继承了 Component 类所具有的接口。但在实现上又表现为has-a Component 的组合关系,即 Decorator 类又使用了另外一个 Component 类。
  • Decorator 模式的目的并非解决 “多子类衍生的多继承” 问题,Decorator 模式应用的要点在于解决 “主体类在多个方向上的扩展功能” —— 是为 “装饰” 的含义。

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

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

相关文章

地理空间数据存储与处理:MySQL空间数据类型的优化与应用!

在 MySQL 数据库中,空间数据类型用于存储和处理地理空间数据。这些数据类型允许我们在开发时可在数据库中存储和操作地理位置、几何形状和地理空间关系等信息。 一、什么是空间数据类型 MySQL 中的空间数据类型主要包括以下几种: GEOMETRY&#xff1a…

iMazing只能苹果电脑吗 Win和Mac上的iMazing功能有区别吗

在当今数字时代,管理和备份手机数据变得越来越重要。无论是转移照片、备份短信,还是管理应用程序,一个强大的工具可以大大简化这些操作。iMazing作为一款备受好评的iOS设备管理软件,已经成为许多用户的选择。但是,许多…

SpringBoot+ElasticSearch7.12.1+Kibana7.12.1简单使用

案例简介 本案例是把日志数据保存到Elasticsearch的索引中,并通过Kibana图形化界面的开发工具给查询出来添加的日志数据,完成从0到1的简单使用 ElasticSearch职责用法简介 ElasticSearch用在哪 ElasticSearch在我这个案例中,不是用来缓解增…

STM32编码器接口解析及抗噪声措施探讨

1. 引言 在现代控制系统中,编码器扮演着非常重要的角色。它就像一个精密的测量工具,可以告诉我们机械部件的位置和运动状态。在STM32微控制器中,编码器接口可以轻松地与各种编码器连接,实现精确的控制。我将在这里探讨STM32编码器…

图文深入理解Oracle Network配置管理(一)

List item 本篇图文深入介绍Oracle Network配置管理。 Oracle Network概述 Oracle Net 服务 Oracle Net 监听程序 <oracle_home>/network/admin/listener.ora <oracle_home>/network/admin/sqlnet.ora建立网络连接 要建立客户机或中间层连接&#xff0c;Oracle…

sublime配置(竞赛向)

我也想要有jiangly一样的sublime 先决条件 首先&#xff0c;到官网上下载最新的sublime4&#xff0c;然后在mingw官网上下载最新的mingw64 mingw64官网&#xff1a;左边菜单栏点击dowloads,然后选择MinGW-W64-builds(可能会有点慢)——然后有时候会变成选LLVM-minGW,接着选择…

人工智能专业就业方向与前景

随着产业结构升级的持续推进&#xff0c;未来行业领域对于人工智能专业人才的需求量会逐渐增加&#xff0c;一部分高校也开始陆续在本科阶段开设人工智能专业&#xff0c;以缓解人工智能领域人才缺口较大的问题。下面是小编整理的人工智能专业就业方向与前景&#xff0c;欢迎阅…

数据结构阶段测试2的一点小补充

数据结构阶段测试2的一点小补充 1.已知⼩根堆为8,15,10,21,34,16,12&#xff0c;删除关键字8之后需重建堆&#xff0c;最后的叶⼦ 节点为() A. 34 B. 21 C. 16 D. 12 解题思路 向下调整算法删除堆顶元素 &#x1f4a1; 答案&#xff1a;C 删除堆顶元素的思路&#xff1a; …

详解Java中的堆内存

详解Java中的堆内存 堆是JVM运行数据区中的一块内存空间&#xff0c;它是线程共享的一块区域&#xff08;注意了&#xff01;&#xff01;&#xff01;&#xff09;&#xff0c;主要用来保存数组和对象实例等&#xff08;其实对象有时候是不在堆中进行分配的&#xff0c;想要了…

python-pptx 中 placeholder 和 shape 有什么区别?

在 python-pptx 库中&#xff0c;placeholder 和 shape 是两个核心概念。虽然它们看起来相似&#xff0c;但在功能和作用上存在显著的区别。为了更好地理解这两个概念&#xff0c;我们可以通过它们的定义、使用场景以及实际代码示例来剖析其差异。 Python-pptx 的官网链接&…

【微服务】服务注册与发现 - Eureka(day3)

CAP理论 P是分区容错性。简单来说&#xff0c;分区容错性表示分布式服务中一个节点挂掉了&#xff0c;并不影响其他节点对外提供服务。也就是一台服务器出错了&#xff0c;仍然可以对外进行响应&#xff0c;不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述&…

【MySQL 06】表的增删查改

目录 1.insert 增添数据 1.1单行数据 全列插入 1.2多行数据 指定列插入 1.3插入否则更新 1.4.插入否则替换 2.select查找 2.1 全列查找 2.2指定列查找 2.3查询字段为表达式 2.4为查询结果指定别名 2.5 结果去重 2.6 where条件查询 2.7结果排序 2.8.筛选分页结果…

指针(7)

目录 1. sizeof和strlen的对⽐ 1.1 sizeof 1.2 strlen sizeof 和 strlen 总结&#xff1a; 2. 数组和指针 2.1 ⼀维数组 2.2 字符数组 1. sizeof和strlen的对⽐ 1.1 sizeof 计算的是使⽤类型创建的变量所占内存空间的⼤⼩。sizeof不在乎你里面放的什么。sizieof是操作符…

指 针

回顾一下&#xff1a; 1. 指针 1.1 基本知识 指针变量——指针&#xff08;存放地址的变量&#xff09; 指针变量所占用的大小&#xff0c;与数据类型无关&#xff0c;跟编译器有关。&#xff08;32位&#xff1a;4字节&#xff0c;64位&#xff1a;8字节&#xff09; 1.2 …

使用阿里云试用资源快速部署web应用-dofaker为例

本文介绍使用阿里云的试用资源部署dofaker的方法&#xff0c;本教程主要作学习在阿里云部署web应用之用&#xff0c;部署好应用之后&#xff0c;可以在任何地点通过公网ip访问web应用。 一、创建云主机 登录阿里云账户之后&#xff0c;点击控制台&#xff1a; 点击云服务器EC…

JavaWeb程序设计(第四版)习题参考答案

JavaWeb程序设计&#xff08;第四版&#xff09;习题参考答案 目录 模块1 习题参考答案 模块2 习题参考答案 模块3 习题参考答案 模块4 习题参考答案 模块5 习题参考答案 模块6 习题参考答案 模块7 习题参考答案 模块8 习题参考答案 模块1 习题参考答案 选择题 1 .A …

模拟退火算法简介

什么是模拟退火算法&#xff1f; 模拟退火算法&#xff08;Simulated Annealing&#xff0c;SA&#xff09;是一种基于随机化搜索的优化算法&#xff0c;灵感来源于金属退火过程。在金属制造中&#xff0c;金属被加热到高温并缓慢冷却&#xff0c;这一过程可以减少内部缺陷&am…

L111213 【哈工大_操作系统】内核级线程内核级线程实现操作系统之“树”

L2.4 内核级线程 切换进程&#xff0c;实际上是切换内核级线程&#xff0c;没有用户级进程说法&#xff0c;进程只能在内核中。 多核与多处理器的区别在于是否共用资源。多核多线程 并发&#xff1a;同时触发&#xff0c;交替执行&#xff0c;在一个核上 并行&#xff1a;同…

三菱FX3U定位控制接线示例(脉冲控制伺服)

一、FX3u系列基本单元(DC24V输入) 二、FX3u系列基本单元(晶体管输出) 脉冲输出用端子Y000、 Y001、 Y002为高速响应输出。 三、FX3UPLC链接MR-J4-A伺服连接实例 1、为了安全起见&#xff0c;不仅仅在可编程控制器侧&#xff0c;在伺服放大器侧也请设计正转限位和反转限位的限位…

数字安全新时代:聚焦关键信息基础设施安全保障——The Open Group 2024生态系统架构·可持续发展年度大会盛大来袭

在全球数字化转型的浪潮中&#xff0c;关键信息基础设施&#xff08;Critical Information Infrastructure&#xff0c;简称CII&#xff09;的安全保障已成为各国政府和企业共同关注的焦点。随着技术的飞速发展和网络威胁的日益复杂&#xff0c;如何构建高效、灵活且安全的数字…