C++ 装饰器模式

2023-11-19

什么是装饰器模式?

  • 装饰器模式是一种结构型设计模式,实现了在不改变现有对象结构的的同时又拓展了新的功能;
  • 装饰器本质上是对现有对象的重新包装,同时装饰器又称为封装器;

如何理解装饰器模式

以笔记本电脑为例,当我们购买了一台新笔记本电脑,但我们发现写代码时,屏幕太小,费眼睛,这时候我们有购买了一个24寸的显示器有了显示器又觉得键盘不舒服,这时候购买了一把机械键盘,陆陆续续又购买了鼠标、USB拓展坞
这时我们再回头看,发现笔记本电脑没有做任何的修理,但我们为笔记本拓展了显示器、键盘、鼠标等外设,这些外设不属于笔记本电脑,同时笔记本没有这些外设(一个或多个)也可以正常工作。这就是装饰器的原理

代码描述

我们这里以手机为例,手机的最初功能就是打电话,后来随着智能手机的出现,又开始有了WIFI、拍照等等的功能

  • 首先需要一个手机的接口类
class I_Phone {
public:
	virtual ~I_Phone(){};
	virtual void ShowFunction() = 0;
};
  • 创建几个市面上的手机厂商
class XiaoMi : public I_Phone {
public:
	void ShowFunction() { cout << "This is XiaoMi Moblie Phone" << endl; }
};
class ViVo : public I_Phone {
public:
	void ShowFunction() { cout << "This is ViVo Moblie Phone" << endl; }
};
class Apple : public I_Phone {
public:
	void ShowFunction() { cout << "This is Apple Moblie Phone" << endl; }
};
  • 这时候智能机出现,手机厂商根据自身实力,去给自家手机增加某些新功能,这里随机举几个例子 5G、拍照、云服务
//5G
class Decorator_5G : public I_Phone {
public:
	Decorator_5G(std::shared_ptr<I_Phone> phone) : i_phone_(phone) {}
	void ShowFunction()
	{
		i_phone_->ShowFunction();
		cout << "Function:5G" << endl;
	}
private:
	std::shared_ptr<I_Phone> i_phone_;
};
//拍照
class Decorator_Camera : public I_Phone {
public:
	Decorator_Camera(std::shared_ptr<I_Phone> phone) : i_phone_(phone) {}
	void ShowFunction()
	{
		i_phone_->ShowFunction();
		cout << "Function:Camera" << endl;
	}
private:
	std::shared_ptr<I_Phone> i_phone_;
};
//云服务
class Decorator_CloudService : public I_Phone {
public:
	Decorator_CloudService(std::shared_ptr<I_Phone> phone) : i_phone_(phone) {}
	void ShowFunction()
	{
		i_phone_->ShowFunction();
		cout << "Function:CloudService" << endl;
	}
private:
	std::shared_ptr<I_Phone> i_phone_;
};
  • 这时候如何把这些功能整合到手机上呢
int main()
{
	//最初只有三款手机
	std::shared_ptr<I_Phone> mi_    = std::make_shared<XiaoMi>();
	std::shared_ptr<I_Phone> vivo_  = std::make_shared<ViVo>();
	std::shared_ptr<I_Phone> apple_ = std::make_shared<Apple>();
	//XiaoMi公司给手机拓展的功能
	std::shared_ptr<I_Phone> mi_decorate_ = std::make_shared<Decorator_5G>(mi_);
	mi_decorate_                          = std::make_shared<Decorator_Camera>(mi_decorate_);
	mi_decorate_->ShowFunction();
	cout << endl;
	//vivo公司给手机拓展的功能
	std::shared_ptr<I_Phone> vivo_decorate_ = std::make_shared<Decorator_Camera>(vivo_);
	vivo_decorate_->ShowFunction();
	cout << endl;
	//Apple公司给手机拓展的功能
	std::shared_ptr<I_Phone> apple_decorate_ = std::make_shared<Decorator_Camera>(apple_);
	apple_decorate_                          = std::make_shared<Decorator_CloudService>(apple_decorate_);
	apple_decorate_                          = std::make_shared<Decorator_5G>(apple_decorate_);
	apple_decorate_->ShowFunction();
	cout << endl;

	return 0;
}
  • 最后三种手机拓展的功能结果
    在这里插入图片描述

装饰器模式的思考

装饰器模式的优缺点
优点:

  • 单一职责,每个类只负责自己的功能
  • 通过装饰类拓展功能,无需创建新的子类,就实现了对原有功能的拓展
  • 可以通过不同的装饰类组合拓展多个新功能
  • 可以在运行时添加或删除某些装饰类的功能

缺点:

  • 给原有类装饰的新功能,很难不按照装饰的顺序栈执行
  • 运行时删除某些装饰类很麻烦
  • 多层装饰会让代码变得难以理解

装饰器模式与其他模式的比较

  • 装饰器就是对派生类写法的一种优化方向,一定程度上可以避免代码的无限膨胀。
  • 和适配器模式相比,装饰器模式可以在不改变对象接口的前提下,拓展新功能,并且可以递归组合,这个是适配器无法实现的
  • 装饰器模式和组合模式很像,但装饰器是给被装饰对象拓展新的功能,而组合模式则是对原有的对象不同的叶子节点进行求和。组合对象不修改原有方法调用,重点是在组织不同子对象;装饰者模式在确保只有一个子对象的同时,又对调用执行的方法进行了拓展。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 装饰器模式 的相关文章

  • 是否有与 posix_memalign 对应的 C++ 版本?

    当我打电话时posix memalign http man7 org linux man pages man3 posix memalign 3 html为类型的对象分配对齐的内存Foo在我的 C 代码中 我需要做一个reinterpret
  • 使用 C# 登录《我的世界》

    我正在尝试为自己和一些朋友创建一个简单的自定义 Minecraft 启动器 我不需要启动 Minecraft 的代码 只需要登录的实际代码行 例如 据我所知 您过去可以使用 string netResponse httpGET https
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 如何在C(Linux)中的while循环中准确地睡眠?

    在 C 代码 Linux 操作系统 中 我需要在 while 循环内准确地休眠 比如说 10000 微秒 1000 次 我尝试过usleep nanosleep select pselect和其他一些方法 但没有成功 一旦大约 50 次 它
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 对 std::vector 进行排序但忽略某个数字

    我有一个std vector
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • OpenGL:仅获取模板缓冲区而没有深度缓冲区?

    我想获取一个模板缓冲区 但如果可能的话 不要承受附加深度缓冲区的开销 因为我不会使用它 我发现的大多数资源表明 虽然模板缓冲区是可选的 例如 排除它以利于获得更高的深度缓冲区精度 但我还没有看到任何请求并成功获取仅 8 位模板缓冲区的代码
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 如何减少具有多个单元的 PdfPTable 的内存消耗

    我正在使用 ITextSharp 创建一个 PDF 它由单个 PdfTable 组成 不幸的是 对于特定的数据集 由于创建了大量 PdfPCell 我遇到了内存不足异常 我已经分析了内存使用情况 我有近百万个单元格的 1 2 在这种情况下有
  • 灵气序列解析问题

    我在使用 Spirit Qi 2 4 编写解析器时遇到一些问题 我有一系列键值对以以下格式解析
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐

  • nginx响应码301及访问路径参数丢失之间的关系

    nginx响应码301及访问路径参数丢失之间的关系 本文比较长 所以写了一篇比较短的结果导向的文章 换了一下思路 大家可以看一这篇文章 如果感兴趣再来看这篇文章 nginx导致vue设置history模式下的请求丢失参数 背景描述 在一次生
  • VUE路由的跳转的4中方式

    vue 路由跳转四种方式 带参数 router link 带参数 不带参数 this router push 函数里面调用 1 2 3 this router replce 用法同上 push this router go n 一 1 ro
  • 一步真实解决TypeError: unlink() got an unexpected keyword argument ‘missing_ok‘

    在谷歌服务器colab上跑yolo代码 训练自己的yolov5模型 遇到这个错误 可把我整不会了 已经做好了数据集 建立了新的data下的yaml和model下的yaml文件 然后使用代码 python train py 运行train p
  • 新仙魔九界研发及设计分析

    玩法本质属于捕鱼RPG玩法 美术风格属于国风 非常有特色 目前整体的玩法 性能优化和体验各方面都做的不错 从第三方数据平台获知该游戏目前月流水在600万 且有未来还有巨大的增长空间 这也不是波克城市第一次做出尝试 早在2015年就尝试过一个
  • druid 解析select查询sql获取表名,字段名,where条件

    解析select sql生成QueryModelInfo param dbTypeName mysql oracle param selectSql return public static QueryModelInfo parse Str
  • Vue将页面中Echarts动态图导出Gif动图

    Vue将页面中Echarts动态图导出Gif动图 首先 准备工作需要三个依赖的js 第一个js采用npm进行安装 npm install html2canvas 第二个js采用下载放入项目中进行使用 下载链接 https pan baidu
  • $refs用法

    refs获取dom元素 今天我们主要说一下几点 1 vue 获取普通元素 基础 2 vue 获取列表 基础 一 vue获取dom节点 普通元素 我们之前获取页面上的dom元素 很容易 比如原生js的 document getElements
  • Angular实现发送请求下载文件

    Angular实现下载文件到本地 第一步 获取下载地址 获取下载地址 download let param 参数 json形式 this download param subscribe res any gt if res success
  • 【无标题】AttributeError: ‘TransposedFont‘ object has no attribute ‘getbbox‘

    Python 运行 Wordcloud的时候出现了这个错误 from wordcloud import WordCloud from PIL import Image import matplotlib pyplot as plt topi
  • 3D游戏编程与设计作业——血条预制

    一 作业要求 血条 Health Bar 的预制设计 具体要求如下 分别使用 IMGUI 和 UGUI 实现 使用 UGUI 血条是游戏对象的一个子元素 任何时候需要面对主摄像机 分析两种实现的优缺点 给出预制的使用方法 二 实现效果 血条
  • ROS自学实践(10):ROS节点同时订阅多个话题并进行消息时间同步

    一 前言 在进行SLAM建图或自动驾驶系统设计的过程中 往往涉及到多种传感器进行环境感知和信息采集 这就不仅需要一个节点接收多个传感器数据 还要求传感器数据的时间戳同步 这样才能实现环境数据的实时感知和处理 本文基于ROS操作系统 从C 和
  • Android 5.x 权限问题解决方法

    0 关于selinux的基础知识 可以参见http www cnblogs com shell812 p 6379321 html TE语言规则 参见http www cnblogs com shell812 p 6379370 html
  • npx报错“Path must be a string. Received undefined”in windows解决方法

    在使用Windows上使用较老版本的nodejs 如何我使用的v8 9其自带的npx的版本为9 7 在Windows上使用会存在 Path must be a string Received undefined 的错误 通过 GitHub
  • QT程序运行时依赖设置

    本文主要解决Qt程序运行时容易遇到的两个问题 找不到相关的Qt6Core dll Qt6Widgets dll等库 这种情况下 把相关DLL所在目录添加到系统的环境变量 PATH 中 就可以了 无法导入Qt相关的插件 qt qpa plug
  • PCL调错:(3)error C2589“(“:“::“右边的非法标记

    错误提示 造成该错误的原因是 pcl库中的函数模板max与Visual C 中的全局的宏max冲突 百度了以下看了一共有两种解决方案 第一种不用修改库里边的源代码 设置项目属性 在预定义处理器中添加定义NOMINMAX来禁止使用Visual
  • Android 旧项目引入 (kotlin)插件简单记录

    1 确认自己 AS 的kotlin 插件 已经安装 2 选择kotlin plugin updates 文件显示 3 选择configure kotlin in project 进入选择 Android gradle 的选项 由于我这边配置
  • JAVA中数组冒泡排序和选择排序

    冒泡排序的思想 两两之间比较大小 小的数在前 大的数在后 共比较i 1次 static void MaoPaoArray int a for int i 0 i lt a length 2 i for int j 0 j lt a leng
  • tortoisegit 常见错误disconnected no supported authentication methods available(server sent: publickey)

    本文转载自 https blog csdn net yym6789 article details 53807640 1 安装好小乌龟git后 用小乌龟的pull 从github上拉取项目 遇到错误 disconnected no supp
  • 7 整数反转 c++

    leetcode7 整数反转 题目描述 给出一个 32 位的有符号整数 你需要将这个整数中每位上的数字进行反转 注意 如果反转后整数溢出那么就返回 0 算法思路 使用一个64位的long long类型来存储结果整数 避免反转后结果溢出报错
  • C++ 装饰器模式

    什么是装饰器模式 装饰器模式是一种结构型设计模式 实现了在不改变现有对象结构的的同时又拓展了新的功能 装饰器本质上是对现有对象的重新包装 同时装饰器又称为封装器 如何理解装饰器模式 以笔记本电脑为例 当我们购买了一台新笔记本电脑 但我们发现