当前位置: 首页 > news >正文

设计模式----装饰器模式

在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。

装饰器模式

允许向一个现有的对象添加新的功能,同时又不改变他的结构(进行扩展)。

装饰器模式的结构与实现

通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰器模式的目标。

结构

抽象构件(Component):定义一个抽象接口以规范准备接收附加责任的对象
具体构件(Concrete Component):实现抽象构件,通过装饰器角色为其添加一些职责
抽象装饰(Decorator):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
具体装饰(Concrete Decorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任

装饰器模式UML图

实现

#include <iostream>
#include <string>
using namespace std;//装饰器模式
class Phone
{
public:Phone(){}~Phone(){}virtual void showDecorate(){}
};class iPhone :public Phone
{
private:string _name;
public:iPhone(string name):_name(name){}~iPhone(){}void showDecorate(){cout << _name << "装饰器" << endl;}
};class NokiaPhone :public Phone
{
private:string _name;
public:NokiaPhone(string name):_name(name){}~NokiaPhone(){}void showDecorate(){cout << _name << "装饰器" << endl;}
};class DecoratorPhone :public Phone
{
private:Phone* m_phone;
public:DecoratorPhone(Phone *phone):m_phone(phone){}virtual void showDecorate(){m_phone->showDecorate();}
};class DecoratePhoneA :public DecoratorPhone
{
public:DecoratePhoneA(Phone *phone):DecoratorPhone(phone){}void showDecorate(){DecoratorPhone::showDecorate();AddDecorate();}
private:void AddDecorate(){cout << "增加挂件" << endl;}
};class DecoratePhoneB :public DecoratorPhone
{
public:DecoratePhoneB(Phone* phone):DecoratorPhone(phone){}void showDecorate(){DecoratorPhone::showDecorate();AddDecorate();}
private:void AddDecorate(){cout << "增加屏膜" << endl;}
};void main()
{Phone* phone = new NokiaPhone("6300");Phone* phoneA = new DecoratePhoneA(phone);Phone* phoneB = new DecoratePhoneB(phone);phoneA->showDecorate();phoneB->showDecorate();delete phone; phone = NULL;delete phoneA; phoneA = NULL;delete phoneB; phoneB = NULL;
}

装饰器模式的优缺点

优点:
可以不用修改原有的接口,就可以实现新功能的添加
装饰者可以很方便的转换原有接口中的实现,可以给装饰者指定不同的ConcreteComponent实现不同的功能。
缺点:
复杂性增加,装饰者模式会导致许多小类的产生。

装饰器模式应用场景

前面讲解了关于装饰器模式的结构与特点,下面介绍其适用的应用场景,装饰器模式通常在以下几种情况使用。

当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰器模式却很好实现。
当对象的功能要求可以动态地添加,也可以再动态地撤销时。

相关文章:

设计模式----装饰器模式

在软件开发过程中&#xff0c;有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下&#xff0c;可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。 装饰器模式 允许向一个现有的对象添加新的功能&#xff0c;同时又不改变他的…...

Golang pprof 分析程序的使用内存和执行时间

一、分析程序执行的内存情况 package mainimport ("os""runtime/pprof" )func main() {// ... 你的程序逻辑 ...// 将 HeapProfile 写入文件f, err : os.Create("heap.prof")if err ! nil {panic(err)}defer f.Close()pprof.WriteHeapProfile(f…...

C/C++平方和问题(蓝桥杯)

题目描述&#xff1a; 小明对数位中含有2、0、1、9 的数字很感兴趣&#xff0c;在1 到40 中这样的数包 括1、2、9、10 至32、39 和40&#xff0c;共28 个&#xff0c;他们的和是574&#xff0c;平方和是14362。 注意&#xff0c;平方和是指将每个数分别平方后求和。 请问&#…...

(libusb) usb口自动刷新

文章目录 libusb自动刷新程序Code目录结构Code项目文件usb包code包 效果描述重置reset热拔插使用 END libusb 在操作USB相关内容时&#xff0c;有一个比较著名的库就是libusb。 官方网址&#xff1a;libusb 下载&#xff1a; 下载源码官方编好的库github&#xff1a;Release…...

NLP(一)——概述

参考书: 《speech and language processing》《统计自然语言处理》 宗成庆 语言是思维的载体&#xff0c;自然语言处理相比其他信号较为特别 word2vec用到c语言 Question 预训练语言模型和其他模型的区别? 预训练模型是指在大规模数据上进行预训练的模型&#xff0c;通常…...

智慧公厕:打造智慧城市的环卫明珠

在城市建设中&#xff0c;公共卫生设施的完善和智能化一直是重要环节。而智慧公厕作为智慧城市建设的重要组成部分&#xff0c;发挥着不可替代的作用。本文以智慧公厕源头实力厂家广州中期科技有限公司&#xff0c;大量精品案例现场实景实图&#xff0c;解读智慧公厕如何助力打…...

[LeetBook]【学习日记】寻找链表相交节点

来源于「Krahets」的《图解算法数据结构》 https://leetcode.cn/leetbook/detail/illustration-of-algorithm/ 本题与主站 160 题相同&#xff1a;https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ 训练计划 V 某教练同时带教两位学员&#xff0c;分别以…...

【Python】OpenCV-使用ResNet50进行图像分类

使用ResNet50进行图像分类 如何使用ResNet50模型对图像进行分类。 import os import cv2 import numpy as np from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input, decode_predictions from tensorflow.keras.preprocessing import image# 设置…...

TypeError: `dumps_kwargs` keyword arguments are no longer supported

TypeError: dumps_kwargs keyword arguments are no longer supported 1. 问题描述2. 解决方法 1. 问题描述 使用 FastChat 启动私有大语言模型&#xff0c;通过一些 UI 工具进行访问时&#xff0c;报以下错误。 略 2024-02-29 09:26:14 | ERROR | stderr | yield f"…...

设计模式学习笔记 - 设计原则 - 3.里氏替换原则,它和多态的区别是什么?

前言 今天来学习 SOLID 中的 L&#xff1a;里氏替换原则。它的英文翻译是 Liskov Substitution Principle&#xff0c;缩写为 LSP。 英文原话是&#xff1a; Functions that use points of references of base classes must be able to use objects of derived classes withou…...

java实现图片转pdf,并通过流的方式进行下载(前后端分离)

首先需要导入相关依赖&#xff0c;由于具体依赖本人也不是记得很清楚了&#xff0c;所以简短的说一下。 iText&#xff1a;PDF 操作库&#xff0c;用于创建和操作 PDF 文件。可通过 Maven 或 Gradle 引入 iText 依赖。 MultipartFile&#xff1a;Spring 框架中处理文件上传的类…...

如何系统的学习Python——Python的基本语法

学习Python的基本语法是入门的第一步&#xff0c;以下是一些常见的基本语法概念&#xff1a; 注释&#xff1a; 用#符号来添加单行注释&#xff0c;或使用三引号(或""")来添加多行注释。 # 这是一个单行注释 这是 多行 注释 变量和数据类型&#xff1a; 变量用…...

相机,棱镜和光场

一、成像方法 Imaging Synthesis Capture 1.Synthesis&#xff08;图形学上&#xff09;合成&#xff1a;比如之前学过的光线追踪或者光栅化 2.Capture&#xff08;捕捉&#xff09;&#xff1a;把真实世界存在的东西捕捉成为照片 二、相机 1.小孔成像 利用小孔成像的相…...

【图像版权】论文阅读:CRMW 图像隐写术+压缩算法

不可见水印 前言背景介绍ai大模型水印生成产物不可见水印CRMW 在保护深度神经网络模型知识产权方面与现有防御机制有何不同&#xff1f;使用图像隐写术和压缩算法为神经网络模型生成水印数据集有哪些优势&#xff1f;特征一致性训练如何发挥作用&#xff0c;将水印数据集嵌入到…...

代码随想录算法训练营第31天—贪心算法05 | ● 435. 无重叠区间 ● *763.划分字母区间 ● *56. 合并区间

435. 无重叠区间 https://programmercarl.com/0435.%E6%97%A0%E9%87%8D%E5%8F%A0%E5%8C%BA%E9%97%B4.html 考点 贪心算法重叠区间 我的思路 先按照区间左坐标进行排序&#xff0c;方便后续处理进行for循环&#xff0c;循环范围是0到倒数第二个元素如果当前区间和下一区间重叠…...

2024《》

vue-cli到哪做了那些事 vue-cli是vue.js的脚手架&#xff0c;用于自动生成vue.jswebpack的项目模板&#xff0c;快速搭建Vue.js项目。 vue cli内置了webpack的一些功能&#xff0c;这些是用webpack打包时需要我们自己配置的&#xff0c;例如&#xff1a; 1.ES6代码转换成ES5代…...

【Web】Java反序列化之从CC3看TemplatesImpl的利用

目录 关于TemplatesImpl 关于TemplatesImpl加载字节码 CC3链分析 纯CC3demo 根据CC3改CC6 关于TemplatesImpl TemplatesImpl 是 Java 中的一个类&#xff0c;通常与 Java 反序列化漏洞相关的攻击中被使用。该类位于 Java 标准库中的 javax.xml.transform 包下。 在 Java…...

【Elasticsearch索引】Recovery恢复索引

文章目录 索引恢复恢复列表获取恢复信息响应详细信息正在进行的恢复响应解析高级设置 本地分片恢复事务日志 索引恢复 索引恢复提供了对正在进行的索引分片恢复的洞察。恢复状态可以针对特定的索引报告&#xff0c;也可以在集群范围内报告。 恢复列表 recovery命令是索引分片…...

如何在 Linux 中快速清空文件而不删除它们?

在Linux系统中&#xff0c;清空文件而不删除它们是一种常见的需求&#xff0c;特别是在需要保留文件结构或权限的情况下。本文将详细介绍如何在Linux环境中快速清空文件内容的多种方法&#xff0c;以及每种方法的优缺点。清空文件通常涉及到文件内容的擦除&#xff0c;但并不涉…...

SpringBoot 配置文件${variable:default}用法

${variable:default}用法&#xff0c;variable​是变量名&#xff0c;default​是默认值。如果配置文件中未指定该变量的值&#xff0c;则会使用默认值来替代。 解释代码&#xff1a; ip: ${NACOS_IP:nacos.ip} 该yaml函数是一个配置项&#xff0c;用来指定Nacos服务器的IP地…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

js 设置3秒后执行

如何在JavaScript中延迟3秒执行操作 在JavaScript中&#xff0c;要设置一个操作在指定延迟后&#xff08;例如3秒&#xff09;执行&#xff0c;可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法&#xff0c;它接受两个参数&#xff1a; 要执行的函数&…...