C++设计模式(装饰模式)

一、介绍

1.动机

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

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

 

2.定义

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

 

3.结构图

0167c308773d43d48182a8d411022685.jpeg

 

4.要点总结

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

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

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

 

 

二、装饰模式

1.概念

装饰模式允许在不改变现有对象结构的情况下,动态地为对象添加额外的功能。

①装饰模式的优点:

  • 提供了比继承更灵活的功能扩展机制。
  • 通过使用不同的具体装饰类可以创造出很多不同行为的组合。

②装饰模式的缺点:

  • 由于需要引入更多的类和对象,可能会增加系统的复杂度。
  • 如果装饰器的层次结构设计不当,可能会导致维护困难。

 

2.实现要点

装饰模式实现要点:

  • 抽象构件:定义了对象的接口,所有的具体构件都必须继承或实现这个接口。
  • 具体构件:实现抽象构件的具体类,它是被装饰的对象。
  • 抽象装饰:继承并组合抽象构件,可以通过其子类扩展具体构件的功能。
  • 具体装饰:实现抽象装饰的相关方法,可传入具体构件对象以扩展其功能。

抽象装饰器使用组合是为了传入主体来实现装饰,使用继承是为了规范接口,同时保证包装后不改变原对象的本质。

 

3.示例

//抽象构件
class Coffee {
public:virtual string getName() = 0;virtual double cost() = 0;virtual ~Coffee() {}};//具体构件
class Espresso :public Coffee {
public:virtual string getName() override {return "Espresso";}virtual double cost() override {return 2.5;}
};//具体构件
class Americano :public Coffee {
public:virtual string getName() override {return "Americano";}virtual double cost() override {return 3.0;}
};//具体构件
class Latte :public Coffee {
public:virtual string getName() override {return "Latte";}virtual double cost() override {return 3.5;}
};//抽象装饰器
class CoffeeDecorator :public Coffee {
protected:Coffee* coffee;
public:CoffeeDecorator(Coffee* cof) :coffee(cof) {}virtual ~CoffeeDecorator() {delete coffee;}
};//具体装饰器
class SugarDecorator : public CoffeeDecorator {
public:SugarDecorator(Coffee* cof) :CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Sugar";}virtual double cost() override {return coffee->cost() + 0.2;}
};//具体装饰器
class MilkDecorator :public CoffeeDecorator {
public:MilkDecorator(Coffee* cof) :CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Milk";}virtual double cost() override {return coffee->cost() + 0.5;}
};//具体装饰器
class CreamDecorator :public CoffeeDecorator {
public:CreamDecorator(Coffee* cof): CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Cream";}virtual double cost() override {return coffee->cost() + 0.8;}
};

测试代码:

Coffee* espresso = new Espresso();
cout << espresso->getName() << " " << espresso->cost() << endl;
espresso = new SugarDecorator(espresso);
cout << espresso->getName() << " " << espresso->cost() << endl;
espresso = new MilkDecorator(espresso);
cout << espresso->getName() << " " << espresso->cost() << endl;
delete espresso;Coffee* americano = new Americano();
cout << americano->getName() << " " << americano->cost() << endl;
Coffee* americano1 = new SugarDecorator(americano);
cout << americano1->getName() << " " << americano1->cost() << endl;
Coffee* americano2 = new CreamDecorator(americano1);
cout << americano2->getName() << " " << americano2->cost() << endl;
delete americano2;Coffee* latte = new Latte();
cout << latte->getName() << " " << latte->cost() << endl;
MilkDecorator* milk = new MilkDecorator(latte);
cout << milk->getName() << " " << milk->cost() << endl;
CreamDecorator* cream = new CreamDecorator(milk);
cout << cream->getName() << " " << cream->cost() << endl;
delete cream;

输出结果:

Espresso 2.5
Espresso Sugar 2.7
Espresso Sugar Milk 3.2
Americano 3
Americano Sugar 3.2
Americano Sugar Cream 4
Latte 3.5
Latte Milk 4
Latte Milk Cream 4.8

 

 

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

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

相关文章

Spring Cloud(Kilburn 2022.0.2版本)系列教程(五) 服务网关(SpringCloud Gateway)

Spring Cloud(Kilburn 2022.0.2版本)系列教程(五) 服务网关(SpringCloud Gateway) 一、服务网关 1.1 什么是网关 在微服务架构中&#xff0c;服务网关是一个至关重要的组件。它作为系统的入口&#xff0c;负责接收客户端的请求&#xff0c;并将这些请求路由到相应的后端服务…

MySQL底层概述—7.优化原则及慢查询

大纲 1.Explain概述 2.Explain详解 3.索引优化数据准备 4.索引优化原则详解 5.慢查询设置与测试 6.慢查询SQL优化思路 1.Explain概述 使用Explain关键字可以模拟查询优化器来执行SQL查询语句&#xff0c;从而知道MySQL是如何处理SQL语句的&#xff0c;从而分析出查询语句…

【前端】Vue3+Vite如何进行多环境配置呢

在项目或产品的迭代过程中需要分不同的环境&#xff0c;那么使用vitevue3开发时&#xff0c;该如何进行配置呢 1、添加配置文件 .env.xxx .env.xxx 需要与src在同一级目录下 例如&#xff1a; 开发环境&#xff1a; .env.development 开发环境&#xff1a; .env.test 生产环…

FreeSWITCH 简单图形化界面36 -使用mod_sms发送短消息

FreeSWITCH 简单图形化界面36 -使用mod_sms发送短消息 0、测试环境1、mod_sms模块安装2、编写聊天规则2.1 使用xml文件测试一下 2.2 使用脚本文件测试一下 0、测试环境 http://myfs.f3322.net:8020/ 用户名&#xff1a;admin&#xff0c;密码&#xff1a;admin FreeSWITCH界面…

广域网技术

企业需要通过广域网将这些分散在不同地理位置的分支机构连接起来 早期广域网技术概述 广域网&#xff1a;连接不同地区局域网的网络&#xff0c;能够横跨几个洲提供远距离通信&#xff0c;形成国际性的远程网络 广域网设备角色介绍&#xff1a; CE&#xff1a;用户端连接服务…

[GKCTF 2021]签到

[GKCTF 2021]签到 wireshark跟踪http流&#xff0c;基本编解码&#xff0c;倒叙&#xff0c;栅栏密码 找到cat /f14g 把包里返回的字符串先hex解码&#xff0c;再base64解码&#xff0c;看到一个时间是倒叙&#xff0c;不含flag 继续往下面翻&#xff0c;可以看到cat%2Ff14g%7…

ROS VSCode调试方法

VSCode 调试 Ros文档 1.编译参数设置 cd catkin_ws catkin_make -DCMAKE_BUILD_TYPEDebug2.vscode 调试插件安装 可在扩展中安装(Ctrl Shift X): 1.ROS 2.C/C 3.C Intelliense 4.Msg Language Support 5.Txt Syntax 3.导入已有或者新建ROS工作空间 3.1 导入工作…

Socket编程(TCP/UDP详解)

前言&#xff1a;之前因为做项目和找实习没得空&#xff0c;计算机网络模块并没有写成博客&#xff0c;最近得闲了&#xff0c;把计算机网络模块博客补上。 目录 一&#xff0c;UDP编程 1&#xff09;创建套接字 2&#xff09;绑定端口号 3&#xff09;发送与接收数据 4&…

虚拟机VMware安装OpenWrt镜像

前提已经安装VMware Workstation Pro,我使用的是VM16 一.下载OpenWrt系统固件 固件有很多种&#xff0c;我选择下面这个链接的固件: Index of /releases/23.05.3/targets/x86/64/ 二.把固件转换成虚拟机能识别的格式 转换工具下载地址&#xff1a;https://www.starwindsoft…

【Canvas与雷达】点鼠标可暂停金边蓝屏雷达显示屏

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>点鼠标可暂停金边蓝屏雷达显示屏 Draft1</title><style typ…

计算机编码存储+char占用空间+final作用

内存中存储的是对应的编码&#xff0c;与对应的形状库一起能够在显示器显示出来对应的字符。 磁盘中存储的是文件信息。 内存中存储的是变量&#xff08;虽然也是在磁盘里&#xff0c;等到使用的时候再调入进来&#xff09;。 因为编码实质就是二进制串&#xff0c;所以也可以比…

vue3项目搭建-6-axios 基础配置

axios 基础配置 安装 axios npm install axios 创建 axios 实例&#xff0c;配置基地址&#xff0c;配置拦截器,目录&#xff1a;utils/http.js 基地址&#xff1a;在每次访问时&#xff0c;自动作为相对路径的根 // axios 基础封装 import axios from "axios";…

2-2-18-9 QNX系统架构之文件系统(一)

阅读前言 本文以QNX系统官方的文档英文原版资料为参考&#xff0c;翻译和逐句校对后&#xff0c;对QNX操作系统的相关概念进行了深度整理&#xff0c;旨在帮助想要了解QNX的读者及开发者可以快速阅读&#xff0c;而不必查看晦涩难懂的英文原文&#xff0c;这些文章将会作为一个…

Python基于滑动窗口CNN损伤梁桥数据、故宫城墙图像数据分类可视化|数据分享

全文链接&#xff1a;https://tecdat.cn/?p38442 分析师&#xff1a;Yufei Guo 在现代土木结构工程领域&#xff0c;结构损伤的准确识别与定位对于保障基础设施的安全性和耐久性具有极为关键的意义。传统的人工检查方法&#xff0c;如目视检查以及借助专业设备进行检测&#x…

MyBatis的if标签的基本使用

在MyBatis框架中&#xff0c;if标签用于在构建SQL语句时&#xff0c;根据参数条件判断的结果&#xff0c;动态地选择加入或不加where条件中。 一 常见使用 在使用MyBatis处理查询逻辑的时候&#xff0c;常用的是判断一些参数是否为空&#xff0c;列举常用的几种情况展示 1.1…

RabbitMQ原理架构解析:消息传递的核心机制

文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1、简单模式3.2、工作模式3.3、发布订阅3.4、路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1、单机部署5.2、集群部署&#xff08;镜像模式&#xff09;5.3、K8s部署…

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介…

【0346】Postgres内核 Startup Process 通过 signal 与 postmaster 交互实现 (5)

1. Startup Process 进程 postmaster 初始化过程中, 在进入 ServerLoop() 函数之前,会先通过调用 StartChildProcess() 函数来开启辅助进程,这些进程的目的主要用来完成数据库的 XLOG 相关处理。 如: 核实 pg_wal 和 pg_wal/archive_status 文件是否存在Postgres先前是否发…

说说Elasticsearch拼写纠错是如何实现的?

大家好&#xff0c;我是锋哥。今天分享关于【说说Elasticsearch拼写纠错是如何实现的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 说说Elasticsearch拼写纠错是如何实现的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Elasticsearch 中&…

NAT拓展

NAT ALG&#xff08;NAT应用级网&#xff09; 为某些应用层协议&#xff0c;因为其报文内容可能携带IP相关信息&#xff0c;而普通NAT转化无法将这些IP转化&#xff0c;从而导致协议无法正常运行 例如FTP&#xff0c;DHCP&#xff0c;RSTP&#xff0c;ICMP&#xff0c;IPSEC…