设计模式:装饰模式

news2024/11/24 0:19:41

1、装饰模式

1)定义

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

2)动机(motivation)

> 在某些情况下我们可能会“多度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。

> 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低?

3)类图

Component:定义一个对象接口,可以给这些对象动态地添加职责。

ConcreteComponent:定义一个具体的对象,也可以给这个对象添加一些职责。

Decorator:装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。

ConcreteDecoratorA:具体的装饰对象,起到给Component添加职责的功能。

4)代码实现

#include<iostream>
#include<memory>
using namespace std;

//流业务操作
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:
	char Read(int number) override {
		//读文件流
		std::cout << "* read file stream *" << std::endl;
		return 0;
	}
	void Seek(int position) override {
		//定位文件流
		std::cout << "* seek file stream *" << std::endl;
	}
	void Write(char data) override {
		//写文件流
		std::cout << "* write file stream *" << std::endl;
	}
};

class NetworkStream :public Stream {
public:
	char Read(int number) override {
		//读网络流
		std::cout << "* read network stream *" << std::endl;
		return 0;
	}
	void Seek(int position) override {
		//定位网络流
		std::cout << "* read network stream *" << std::endl;
	}
	void Write(char data) override {
		//写网络流
		std::cout << "* read network stream *" << std::endl;
	}
};

class MemoryStream :public Stream {
public:
	char Read(int number) override {
		//读内存流
		std::cout << "* read memory stream *" << std::endl;
		return 0;
	}
	void Seek(int position) override {
		//定位内存流
		std::cout << "* read memory stream *" << std::endl;
	}
	void Write(char data) override {
		//写内存流
		std::cout << "* read memory stream *" << std::endl;
	}
};

class DecoratorStream : public Stream { //继承-接口规范
public:
	DecoratorStream(Stream* _s):s(std::move(_s))
	{}
protected:
	//组合-复用实现
	Stream* s;// =new FileSream, new Networkstream, ...
};

//扩展操作
class CryptoStream : public DecoratorStream {
public:
	using DecoratorStream::DecoratorStream;

	char Read(int number) override {
		std::cout << "* Crypto Operation *" << std::endl;
		s->Read(number);//读流
		return 0;
	}
	void Seek(int position) override {
		std::cout << "* Crypto Operation *" << std::endl;
		s->Seek(position);//定位流
	}
	void Write(char data)override {
		std::cout << "* Crypto Operation *" << std::endl;
		s->Write(data);//写流
	}
};

class BufferedStream : public DecoratorStream {
public:
	using DecoratorStream::DecoratorStream;

	char Read(int number) override {
		std::cout << "* Buffer Operation *" << std::endl;
		s->Read(number);//读流
		return 0;
	}
	void Seek(int position) override {
		std::cout << "* Buffer Operation *" << std::endl;
		s->Seek(position);//定位流
	}
	void Write(char data)override {
		std::cout << "* Buffer Operation *" << std::endl;
		s->Write(data);//写流
	}
};

int main()
{
	std::cout << "----------------读文件流--------------" << std::endl;
	Stream* file_stream = new FileStream();
	file_stream->Read(0);
	std::cout << std::endl;

	std::cout << "----------------加密+读文件流--------------" << std::endl;
	Stream* cryto_stream = new CryptoStream(file_stream);
	cryto_stream->Read(0);
	std::cout << std::endl;

	std::cout << "----------------缓存+加密+读文件流--------------" << std::endl;
	Stream* buff_cryto_stream = new BufferedStream(cryto_stream);
	buff_cryto_stream->Read(0);
	std::cout << std::endl;

	delete buff_cryto_stream;
	delete cryto_stream;
	delete file_stream;

	system("pause");
	return 0;
}

运行结果如下:

 5)要点总结

> 通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生的问题”。

> Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类使用了另外一个Component类。

> Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在与解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。

 

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

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

相关文章

Harbor安装部署实战详细手册

文章目录前言一、安装docker二、安装docker-compose1.下载2.赋权3.测试三、安装harbor1.下载2.解压3.修改配置文件4.部署5.配置开机自启动6.登录验证7.补充说明四、harbor使用问题1.docker login问题&#xff1a;Error response from daemon: Get https://: http: server gave …

Ubuntu 安装 Qt5.7.0

下载 地址&#xff1a;https://download.qt.io/https://download.qt.io/ 文件夹说明&#xff1a; snapshots&#xff1a;预览版&#xff0c;该文件夹中包含最新的测试版本。 online&#xff1a;在线安装包。 official_releases&#xff1a;最终发布版。 new_archive&#…

netcore构建webservice以及调用的完整流程

目录构建前置准备编写服务挂载服务处理SoapHeader调用添加服务调用服务补充内容构建 前置准备 框架版本要求&#xff1a;netcore3.1以上 引入nuget包 SoapCore 编写服务 1.编写服务接口 示例 using System.ServiceModel;namespace Services;[ServiceContract(Namespace &…

Elasticsearch 安装(二)

目录前言一、Linux 安装1、下载安装包⑴、选择需要的安装包⑵、下载解压到安装目录2、查看解压后目录结构3、启动 Elasticsearch⑴、正常启动流程⑵、启动过程遇到的问题①、启动报错②、创建运行 Elasticsearch 的用户&#xff0c;启动成功&#xff0c;但无法访问③、停止Elas…

【pytorch框架】对模型知识的基本了解

文章目录TensorBoard的使用1、TensorBoard启动&#xff1a;2、使用TensorBoard查看一张图片3、transforms的使用pytorch框架基础知识1 nn.module的使用2 nn.conv2d的使用3、池化(MaxPool2d)4 非线性激活5 线性层6 Sequential的使用7 损失函数与反向传播8 优化器9 对现有网络的使…

Flink X Hologres 构建企业级 Streaming Warehouse

摘要&#xff1a;本文整理自阿里云资深技术专家&#xff0c;阿里云 Hologres 负责人姜伟华&#xff08;果贝&#xff09;&#xff0c;在 FFA 实时湖仓专场的分享。本篇内容主要分为四个部分&#xff1a;实时数仓分层的技术需求阿里云一站式实时数仓 Hologres 介绍Flink x Holog…

30个题型+代码(冲刺2023蓝桥杯)

愿意的可以跟我一起刷&#xff0c;每个类型做1~5题 &#xff0c;4月前还可以回来系统复习 2月13日 ~ 3月28日&#xff0c;一共32天 一个月时间&#xff0c;0基础省三 --> 省二&#xff1b;基础好点的&#xff0c;省二 --> 省一 目录 &#x1f33c;前言 &#x1f33c…

1.1配置单区域OSPF

实验1:配置单区域OSPF[1] 1.实验目的 实现单区域OSPF的配置描述OSPF在多路访问网络中邻居关系建立的过程2.实验拓扑 单区域的OSPF实验拓扑如图1-2所示。 图1-2 配置单区域OSPF 3.实验步骤 IP地址的配置[2] R1的配置

Framebuffer驱动程序框架

Framebuffer驱动程序框架 文章目录Framebuffer驱动程序框架一、 怎么编写字符设备驱动程序二、 Framebuffer驱动程序框架三、 怎么编写Framebuffer驱动程序致谢一、 怎么编写字符设备驱动程序 驱动主设备号构造file_operations结构体&#xff0c;填充open/read/write等成员函数…

获取本机的IP地址,看似简单的获取,实则蕴含非常多的操作

这篇文章讲述了PowerJob获取本地IP离奇曲折的经过&#xff0c;以及开放了诸多的可配置参数&#xff0c;打开了我新世界的大窗户。求个关注&#xff0c;求个点赞&#xff0c;求一个评论。 获取地址的操作&#xff0c;本来不应该作为什么重点&#xff0c;但是因为一点小小的意外&…

再创荣誉 | Softing工业荣获CAIMRS 2023 数字化创新奖

在刚刚结束的中国工控-第二十一届“自动化及数字化”年度评选&#xff08;CAIMRS 2023&#xff09;中&#xff0c;Softing凭借edgeAggregator产品荣获“数字化创新奖”&#xff01; 经层层筛选&#xff0c;Softing edgeAggregator边缘聚合服务器从中脱颖而出&#xff0c;摘得C…

隐马尔科夫模型基础

一、定义是一种生成模型&#xff0c;是隐藏的马尔科夫链随机生成不可观测的状态序列&#xff0c;再由各个状态生成观测序列的过程二、符号含义其中&#xff1a;Q是所有可能的状态集合V是所有的可能的观测集合N是可能的状态数&#xff0c;M是可能的观测数其中&#xff1a;I是长度…

想搞钱,先培养商业思维!

昨天谈借助 ChatGPT 挣点房贷钱的时候&#xff0c;看评论区大家留言的时候&#xff0c;发现很多人不知道这个东西可以赚钱&#xff0c;或者说知道这个东西且也做了功课&#xff0c;无奈太忙最后也没搞到钱。可以看到&#xff0c;大家的问题&#xff0c;归根于自己有没有商业思维…

小白系列Vite-Vue3-TypeScript:010-封装svg

上一篇我们介绍了ViteVue3TypeScript项目中mockjs的安装和配置i。本篇我们来介绍封装SVG图标组件。svg特征Preloading所有图标都是在项目运行时生成的&#xff0c;只需要操作一次dom即可。高性能内置缓存&#xff0c;仅在文件被修改时才会重新生成。安装插件vite-plugin-svg-ic…

QHash源码解读

QT版本 v5.12.10 元素 // 重点说明QHashData的函数&#xff0c;QHashData是QHash的基础 struct QHashData {struct Node {Node *next;uint h;};Node *fakeNext; // 永为nullNode **buckets; // Node *数组QtPrivate::RefCount ref;int size; // node个数int nodeSize; /…

koa2结合MySQL实现简单的考试系统

项目需求:1. 数据库采用mysql实现, 后台服务Koa2框架, 通过postman调试所有接口2. 接口功能&#xff1a;(1)实现对科目表的增删改查(2)实现对试题表的增删改(3)实现对试题表的查询操作&#xff0c;要求&#xff1a;<1>显示科目名称和类型名称 <2> 可以按照科目名称…

第一章 - 对数据库和SQL的简单了解

第一章 - 对数据库和SQL的简单了解1 了解数据库&#xff1a;2 什么是数据库&#xff1a;3 什么是SQL&#xff1a;4 SQL的优点&#xff1a;5 数据库的一些常用术语&#xff1a;6 什么是MySQL&#xff1a;1 了解数据库&#xff1a; 其实你一直都在使用数据库&#xff0c;只是你并…

【观察】从消费级SSD AM6A1,看忆联的优势与胜势

毫无疑问&#xff0c;目前SSD&#xff08;固态硬盘&#xff09;已取代HDD&#xff08;机械硬盘&#xff09;成为电脑中常见的存储设备&#xff0c;特别是在技术创新的持续推动下&#xff0c;如今SSD的速度和效率都在不断地提高&#xff0c;从SATA2 3GB发展到SATA3 6GB&#xff…

四、常用样式讲解二

文章目录一、常用样式讲解二1.1 元素隐藏1.2 二级菜单1.3 相对定位和绝对定位1.4 定位的特殊情况1.5 表格1.6 表格的css属性1.7 表格中新增的标签一、常用样式讲解二 1.1 元素隐藏 如何让一个元素隐藏 1、不定义颜色 占用空间 2、display: none 不占用空间 3、visibility: hi…

在Linux和Windows上安装Nacos-2.1.1

记录&#xff1a;377场景&#xff1a;在CentOS 7.9操作系统安装Nacos-2.1.1。在Windows操作系统上安装Nacos-2.1.1。Nacos&#xff1a;Nacos: Dynamic Naming and Configuration Service。Nacos提供动态配置服务、服务发现及管理、动态DNS服务功能。版本&#xff1a;JDK 1.8 Na…