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

设计模式-结构型-装饰器模式

装饰器模式(Decorator Pattern)是结构型设计模式中的一种,它允许你通过将对象封装在一个新的对象中,来动态地添加新的功能,而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”,它是一种对象行为增强的模式。该模式通过组合而非继承来扩展对象的功能,这使得它比继承更灵活。

装饰器模式的定义

装饰器模式允许在不修改对象本身的情况下,动态地给一个对象添加额外的功能。其基本结构如下:

  • Component:定义一个对象接口,可以为其他对象提供基础功能。
  • ConcreteComponent:实现 Component 接口的具体类,是需要被装饰的原始对象。
  • Decorator:持有一个 Component 对象,并通过继承或实现该接口来增加附加功能。
  • ConcreteDecorator:具体的装饰类,它实现了装饰器接口,包装了 ConcreteComponent,并增加了新的功能。

装饰器模式的实现

在 Python 中,装饰器模式通常使用类继承组合的方式实现。为了更清晰地理解装饰器模式,我们可以通过一个示例进行讲解。

代码示例

假设我们有一个 Car 类,表示普通的汽车,车主希望能够动态地为这辆车添加新功能,例如导航系统和音响系统。我们可以通过装饰器模式为 Car 类动态地增加这些功能。

# 1. 基础组件接口
class Car:def features(self):raise NotImplementedError("Subclass must implement abstract method")# 2. 具体组件:原始的汽车类
class BasicCar(Car):def features(self):return "Basic Car Features"# 3. 装饰器类:持有一个 Car 对象
class CarDecorator(Car):def __init__(self, car):self._car = cardef features(self):return self._car.features()# 4. 具体装饰器:为汽车添加导航功能
class NavigationSystem(CarDecorator):def features(self):return f"{self._car.features()}, Navigation System"# 5. 具体装饰器:为汽车添加音响系统
class SoundSystem(CarDecorator):def features(self):return f"{self._car.features()}, Sound System"# 使用装饰器
basic_car = BasicCar()
print("Basic Car:", basic_car.features())# 添加导航功能
car_with_navigation = NavigationSystem(basic_car)
print("Car with Navigation:", car_with_navigation.features())# 添加音响功能
car_with_navigation_and_sound = SoundSystem(car_with_navigation)
print("Car with Navigation and Sound System:", car_with_navigation_and_sound.features())

输出结果

Basic Car: Basic Car Features

Car with Navigation: Basic Car Features, Navigation System

Car with Navigation and Sound System: Basic Car Features, Navigation System, Sound System

解释

  • BasicCar:原始汽车类,实现了 Car 接口,提供了基本的汽车功能。
  • CarDecorator:装饰器基类,它持有一个 Car 对象,并通过 features() 方法传递对原始 Car 功能的调用。
  • NavigationSystemSoundSystem:具体的装饰类,它们分别为汽车增加了导航和音响功能。

通过使用装饰器模式,我们可以动态地为 Car 添加新功能,而无需修改 BasicCar 类本身。

装饰器模式的优点

  1. 增强功能的灵活性

    • 通过装饰器模式,可以在运行时根据需求动态地为对象增加功能,而无需修改类的代码。它提供了一种非常灵活的方式来增强对象的行为。
  2. 符合开闭原则

    • 装饰器模式符合设计原则中的开闭原则:对扩展开放,对修改关闭。你可以通过装饰器为现有类添加新功能,而无需修改现有代码。
  3. 避免了继承层次的膨胀

    • 通过装饰器模式,我们不需要使用继承来增加新功能,从而避免了继承层次的复杂性。每个装饰类只负责一个功能,可以随意组合,避免了多重继承的繁琐。
  4. 组合与复用

    • 装饰器模式支持多重组合,可以灵活地为对象组合多个功能,每个功能都可以由不同的装饰器来处理,使得代码复用性更高。

装饰器模式的缺点

  1. 增加系统复杂度

    • 尽管装饰器模式提供了灵活的扩展性,但在实际使用时,过多的装饰器类可能导致系统变得复杂,难以管理和理解。
  2. 类数量激增

    • 每一个新的装饰类都可能成为系统中的一个新类。如果有很多功能需要动态添加,可能会导致类的数量剧增,增加系统的维护成本。
  3. 调试困难

    • 在使用装饰器模式时,调试可能会变得更加困难,因为装饰器通常是动态地改变对象的行为,跟踪这些变化可能需要更多的调试工具支持。

装饰器模式的实际应用

装饰器模式在许多实际应用中都有广泛的使用,特别是在需要动态增强对象功能的场景中。以下是一些典型应用场景:

  1. 输入输出流

    • 在 Java 中,装饰器模式常用于输入输出流的处理(例如:BufferedReaderFileReader)。每个类都为流对象添加不同的功能,而不需要修改原始对象的代码。
  2. GUI控件

    • 在图形用户界面(GUI)中,装饰器模式常用于为界面组件(如按钮、文本框)动态添加功能。例如,动态为按钮添加点击事件、为文本框添加验证功能等。
  3. Web开发中的请求处理

    • 在 Web 开发中,装饰器模式通常用于处理 HTTP 请求和响应,例如:在请求进入处理函数前动态地为请求添加身份验证、日志记录、权限控制等功能。
  4. 缓存和日志

    • 通过装饰器模式,可以在现有功能的基础上为数据处理添加缓存或日志功能,而不需要修改核心业务逻辑。

总结

装饰器模式是一种强大的设计模式,提供了一种灵活的方式来扩展对象的功能。通过将对象封装在另一个对象中,装饰器可以在不修改原始对象的情况下,为对象添加新的行为。这种模式使得我们可以通过组合多个装饰器来动态增加功能,而避免了类继承的复杂性,符合“开闭原则”。然而,过度使用装饰器模式可能导致系统复杂度和类数量的激增,因此需要谨慎使用。

相关文章:

设计模式-结构型-装饰器模式

装饰器模式(Decorator Pattern)是结构型设计模式中的一种,它允许你通过将对象封装在一个新的对象中,来动态地添加新的功能,而无需改变原对象的结构。装饰器模式的核心思想是“将功能附加到对象上”,它是一种…...

CAP:Serverless + AI 让应用开发更简单

AI 已被广泛视为推动行业进步的关键力量,其在各行业的落地步伐加快。企业在构建 AI 应用开发过程中经常会面临 AI 技术门槛过高、试错周期过长、GPU 资源昂贵且弹性能力不足、缺乏配套工具、业务与模型的开发运维过于割裂、缺乏定制化能力等挑战,成为企业…...

Redis超详细入门教程(基础篇)

目录 一、什么是Redis 二、安装Redis 1、Windows系统安装 2、Linux系统安装 三、Redis通用命令 四、Redis基本命令 五、五种数据结构类型 5.1、String类型 5.2、List集合类型 5.3、Set集合类型 5.4、Hash集合类型 5.5、Zset有序集合类型 六、总结 一、什么是Redi…...

对话 TDengine 解决方案中心总经理陈肃:构建技术与市场的桥梁

TD 小T导读 他是大数据领域的杰出专家,拥有超过十项一作发明专利,是中国通信行业标准《大数据 消息中间件技术要求与测试方法》的重要编写者,并凭借数据中间件领域的突出成就荣获 2019 年“CJK OSS Award”。他是腾讯云 TVP 专家和 TGO 鲲鹏会…...

Formality:参考设计/实现设计以及顶层设计

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482​​​ Formality存在两个重要的概念:参考设计/实现设计和顶层设计,本文就将对此进行详细阐述。参考设计/实现设计是中两个重要的全局概念&am…...

通过内核模块按fd强制tcp的quickack方法

一、背景 tcp的quickack功能是为了让ack迅速回发,快速响应,减少网络通讯时延,属于一个优化项,但是tcp的quickack是有配额限制的,配置是16个quick,也就是短时间内quickack了16次以后,这个配额为…...

Wi-Fi 7、Wi-Fi 6 与 5G、4G 的全方位对比

随着无线通信技术的飞速发展,Wi-Fi 7、Wi-Fi 6,以及5G、4G 已经成为人们生活和工作中不可或缺的网络技术。无论是家庭网络、高速移动通信,还是工业物联网,这些技术都在发挥各自的作用。那么,它们之间有什么区别&#x…...

【例43.3】 转二进制

目录 描述 输入描述 输出描述 用例输入 1 用例输出 1 来源 类型 知识补充站 代码 C Python3 C 描述 请你把一个整数n转化为二进制并从低位到高位输出。 输入描述 一行,仅含一个正整数 n (1≤n≤109)。 输出描述 从低位到高位输出一个二进制数&a…...

qt vs ios开发应用环境搭建和上架商店的记录

qt 下载链接如下 https://download.qt.io/new_archive/qt/5.14/5.14.2/qt-opensource-mac-x64-5.14.2.dmg 安装选项全勾选就行,这里特别说明下qt5.14.2/qml qt5.14.2对qml支持还算成熟,但很多特性还得qt6才行,这里用qt5.14.2主要是考虑到服…...

安全测评主要标准

大家读完觉得有帮助记得关注和点赞!!! 安全测评的主要标准‌包括多个国际和国内的标准,这些标准为信息系统和产品的安全评估提供了基础和指导。 一、安全测评的主要标准 1.1、国际标准 ‌可信计算机系统评估准则(TC…...

如何学习数学 | 数学家如何思考

学习数学的关键在哪里? 原创 遇见数学 不少人面对数学都会觉得高深莫测,甚至非常枯燥乏味。 只有当你真正走入它的世界,才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门,需要的不仅仅是背公式,或者做一…...

职场沟通与行为

职场沟通与行为 引言 在职场上,你是否曾遇到过困惑的沟通?是否对同事的行为有过疑虑?这不仅是个别现象,而是我们这个时代工作文化中的普遍问题。许多职场的摩擦,来自沟通不畅或是行为不当。那么,如何才能…...

IIO(Industrial I/O)驱动介绍

文章目录 IIO(Industrial I/O)驱动是Linux内核中用于工业I/O设备的子系统,主要用于处理传感器数据采集和转换。以下是其关键点: 功能 数据采集:从传感器读取数据。数据处理:对原始数据进行滤波、校准等操作…...

关于vite+vue3+ts项目中env.d.ts 文件详解

env.d.ts 文件是 Vite 项目中用于定义全局类型声明的 TypeScript 文件。它帮助开发者向 TypeScript提供全局的类型提示,特别是在使用一些特定于 Vite 的功能时(如 import.meta.env)。以下是详细讲解及代码示例 文章目录 **1. env.d.ts 文件的…...

32单片机综合应用案例——物联网(IoT)环境监测站(四)(内附详细代码讲解!!!)

无论你身处何种困境,都要坚持下去,因为勇气和毅力是成功的基石。不要害怕失败,因为失败并不代表终结,而是为了成长和进步。相信自己的能力,相信自己的潜力,相信自己可以克服一切困难。成功需要付出努力和坚…...

【Flink系列】6. Flink中的时间和窗口

6. Flink中的时间和窗口 在批处理统计中,我们可以等待一批数据都到齐后,统一处理。但是在实时处理统计中,我们是来一条就得处理一条,那么我们怎么统计最近一段时间内的数据呢?引入“窗口”。 所谓的“窗口”&#xff…...

代码随想录算法训练营第三十五天-动态规划-01背包(二维)

动规五部曲 dp数组的含义,注意这是一个二维数组。dp[i][j] 第一维度代表“从0到第i个物品,而且包括选或不选的情况,即这一维度代表物品编号第二维度代表代表背包容量合在一起的意思是当背包容量是j时,从0到i个物品中选择任意物品…...

快速开发:用AI构造AI —— 打造属于个人的Copilot(M-聪明AI)

作品简介: 当今快速发展的AI时代,学会使用AI的同时,也可以融入AI,来打造自己的产品,我给我这个取名M-聪明, 是基于VUE 3 Spring Boot -Redis ChatGML RxJava SSE 的AI 服务平台。然后这款工具旨在为用户…...

Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];

AccessDeniedException 表明 Elasticsearch 容器无法访问或写入数据目录 /usr/share/elasticsearch/data/nodes。这是一个权限问题。 问题原因: 1、宿主机目录权限不足:映射到容器的数据目录 /data/es/data 在宿主机上可能没有足够的权限供容器访问。 …...

用公网服务器实现内网穿透

首先需要一个公网服务器 下载frp 搜索github下载到frp,服务端frps/客户端frpc。。下载的时候要注意自己本地内网机的cpu版本和服务端cpu架构 我的电脑是mac M1PRO版本 下载的是:darwinarm64 比如 服务端一般是Linux(Intel 64位CPU&#xf…...

Jmeter如何进行多服务器远程测试

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 JMeter是Apache软件基金会的开源项目,主要来做功能和性能测试,用Java编写。 我们一般都会用JMeter在本地进行测试,但是受到单…...

前端实习第二个月小结

时间飞快,第一次实习已经过去两个多月,作一些简单的总结和分享。 注:文章整体会比较轻松,提及的经历、经验仅作参考。 一、关于实习/工作内容 1、工作内容 近期做的是管理后台方面的业务,技术栈:前端re…...

C# 并发和并行的区别--16

目录 并发和并行 一.并发 定义 特点 代码示例 代码解释 二.并行 定义 特点 在C#中的体现 代码示例 代码解释 三.并发和并行的区别 四 .如何在C#中选择并发还是并行 1.考虑任务类型 2.代码示例 3.注意事项 五.总结 并发和并行 在编程领域,并发和并行是两个密切…...

Python编程与在线医疗平台数据挖掘与数据应用交互性研究

一、引言 1.1 研究背景与意义 在互联网技术飞速发展的当下,在线医疗平台如雨后春笋般涌现,为人们的就医方式带来了重大变革。这些平台打破了传统医疗服务在时间和空间上的限制,使患者能够更加便捷地获取医疗资源。据相关报告显示,中国基于互联网的医疗保健行业已进入新的…...

HBase实训:纸币冠字号查询任务

一、实验目的 1. 理解分布式数据存储系统HBase的架构和工作原理。 2. 掌握HBase表的设计原则,能够根据实际业务需求设计合理的表结构。 3. 学习使用HBase Java API进行数据的插入、查询和管理。 4. 实践分布式数据存储系统在大数据环境下的应用,…...

Java 读取 Windows 设备的唯一性标识及定位

在 Windows 系统中,获取设备唯一性标识及定位信息对设备管理、安全监控等场景意义重大。本文介绍 Java 中几种实现方法,如 JNA 库、WMI4Java 库及通过 JNI 结合 Windows API。 1. 使用 JNA 库读取 DEVPKEY_Device_ContainerId 在 Windows 系统中&…...

UE控件学习

ListView: item设置:使能在list设置为Entry类 Grid Panel: 常用作背包,每个格子大小可不相同 WidgetSwitcher: 用于切换页签 Wrap_Box: 自动横向排版子节点,超过一定范围则自动换行…...

1.Spring AI 从入门到实践

​Spring AI 从入门到实践 1.什么是Spring AI 2.使用Spring Boot&Spring AI快速构建AI应用程序 3.ChatClient&Chat Model简化与AI模型的交互 4.Spring AI Prompt:与大模型进行有效沟通 5.结构化输出大模型响应 6.实战:AI聊天机器人 Ben技术站关注Java技术&#x…...

2025年01月蓝桥杯Scratch1月stema选拔赛真题—美丽的图形

美丽的图形 编程实现美丽的图形具体要求: 1)点击绿旗,角色在舞台中心,如图所示; 2)1秒后,绘制一个边长为 140的红色大正方形,线条粗细为 3,正方形的中心为舞台中心,如图所示; 完整题目可点击下…...

FLASK创建下载

html用a标签 <!-- Button to download the image --> <a href"{{ url_for(download_file, filenameimage.png) }}"><button>Download Image</button> </a> 后端&#xff1a;url_for双大括号即是用来插入变量到模板中的语法。也就是绑…...

LDD3学习7--硬件接口I/O端口(以short为例)

1 理论 1.1 基本概念 目前对外设的操作&#xff0c;都是通过寄存器。寄存器的概念&#xff0c;其实就是接口&#xff0c;访问硬件接口&#xff0c;有I/O端口通信和内存映射I/O (Memory-Mapped I/O)&#xff0c;I/O端口通信是比较老的那种&#xff0c;都是老的串口并口设备&am…...

MySQL(高级特性篇) 06 章——索引的数据结构

一、为什么使用索引 索引是存储引擎用于快速找到数据记录的一种数据结构&#xff0c;就好比一本教科书的目录部分&#xff0c;通过目录找到对应文章的页码&#xff0c;便可快速定位到需要的文章。MySQL中也是一样的道理&#xff0c;进行数据查找时&#xff0c;首先查看查询条件…...

【FlutterDart】MVVM(Model-View-ViewModel)架构模式例子-http版本(30 /100)

动图更精彩 MVVM&#xff08;Model-View-ViewModel&#xff09; 特点 Model&#xff1a;负责数据管理和业务逻辑。 View&#xff1a;负责显示数据&#xff0c;通常是一个UI组件。 ViewModel&#xff1a;负责处理用户交互&#xff0c;更新Model&#xff0c;并将数据转换为View可…...

光谱相机的光谱分辨率可以达到多少?

多光谱相机 多光谱相机的光谱分辨率相对较低&#xff0c;波段数一般在 10 到 20 个左右&#xff0c;光谱分辨率通常在几十纳米到几百纳米之间&#xff0c;如常见的多光谱相机光谱分辨率为 100nm 左右。 高光谱相机 一般的高光谱相机光谱分辨率可达 2.5nm 到 10nm 左右&#x…...

.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)

一、UI效果 二、新建用户控件&#xff1a;VideoViewControl.axaml 需引用&#xff1a;VideoLAN.LibVLC.Windows包 Linux平台需安装&#xff1a;VLC 和 LibVLC &#xff08;sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev&#xff09; .axaml 代码 注…...

【论文阅读】基于空间相关性与Stacking集成学习的风电功率预测方法

文章目录 摘要0. 引言1. 空间相关性分析2. 风电功率预测模型2.1 Stacking 集成策略2.2 基学习器2.2.1 基于机器学习算法的基学习器2.2.2 基于神经网络的基学习器2.2.3 基于粒子群优化算法的超参数优化 2.3 元学习器2.4 基于空间相关性与Stacking集成学习的风电功率预测方法 3 算…...

什么是Spring Boot 应用开发?

一、引言 在当今的软件开发领域&#xff0c;Java 依然占据着重要的地位&#xff0c;而 Spring Boot 作为 Java 生态系统中极具影响力的框架&#xff0c;极大地简化了企业级应用的开发流程&#xff0c;提升了开发效率和应用的可维护性。它基于 Spring 框架构建&#xff0c;通过…...

选择saas 还是源码主要考虑

公司业务规模&#xff1a;小型企业可能会发现SaaS提供的即用型解决方案更符合其需求&#xff0c;而大型企业可能需要源码以实现更高的定制性和控制权。 公司技术专长&#xff1a;缺乏技术团队的企业可能会倾向于使用SaaS&#xff0c;而那些拥有强大IT部门的企业可能更适合管理…...

【JAVA 基础 第(19)课】Hashtable 类用法和注意细节,是Map接口的实现类

Map接口&#xff1a;存放的是具有映射关系的键值对&#xff0c;键映射到值&#xff0c;键必须是唯一的 Hashtable 类&#xff0c;Map接口的实现类,键和值都不能为nullHashtable 是同步的&#xff0c;是线程安全的 public class MapTest {public static void main(String[] arg…...

AI时代下 | 通义灵码冲刺备战求职季

AI时代下 | 通义灵码冲刺备战求职季 什么是通义灵码使用智能编程助手备战求职靠谱吗体验心得 AI时代下&#xff0c;备战求职季有了不一样的方法&#xff0c;使用通义灵码冲刺备战求职季&#xff0c;会有什么样的体验&#xff1f; 什么是通义灵码 在开始话题之前&#xff0c;首…...

如何将 session 共享存储到 redis 中

文章目录 一. 分布式 session 登录1.1 什么是分布式&#xff1f;1.2 Session 共享1.3 为什么服务器 A 登录后&#xff0c;请求发到服务器 B&#xff0c;不认识该用户&#xff1f;1.4 共享存储 二. Session 共享实现Redis三. 测试session共享四. cookie设置4.1 前端4.2 后端 一.…...

智能科技与共情能力加持,哈曼重新定义驾乘体验

2025年1月6日&#xff0c;拉斯维加斯&#xff0c;2025年国际消费电子展——想象一下&#xff0c;当您步入一辆汽车&#xff0c;它不仅能响应您的指令&#xff0c;更能理解您的需求、适应您的偏好&#xff0c;并为您创造一个独特且专属的交互环境。作为汽车科技领域的知名企业和…...

第4章 Kafka核心API——Kafka客户端操作

Kafka客户端操作 一. 客户端操作1. AdminClient API 一. 客户端操作 1. AdminClient API...

Debian 设定 tomcat 定时重启

目录 背景 过程记录 1、编辑sh文件&#xff0c;完成重启功能 2、设置sh的可执行权限 ​编辑 3、设置定时任务 背景 在Debian 12系统中&#xff0c;原本部署了两个tomcat&#xff0c;结果总是遇到CPU飙升到影响应用正常使用的程度&#xff0c;找了很久原因还是没有找到。 …...

mysql8.0 重要指标参数介绍

MySQL 8.0 引入了许多新的功能和优化&#xff0c;针对性能、可扩展性、可靠性以及安全性方面做出了显著改进。为了确保 MySQL 的高效运行&#xff0c;了解和配置 MySQL 的一些关键指标参数非常重要。以下是 MySQL 8.0 中的一些重要参数和指标&#xff0c;帮助你优化数据库性能。…...

SpringMVC (2)

目录 1. RequestMapping 注解介绍 2. RequestMapping 使用 3. RequestMapping与请求方式 3.1 RequestMapping 支持Get和Post类型的请求 3.2 RequestMapping 指定接收某种请求 3.3 GetMapping和PostMapping 4. 传参 4.1 通过查询字符串传参 4.2 在 Body 中传参 4.2.1 …...

【全面解析】深入解析 TCP/IP 协议:网络通信的基石

深入解析 TCP/IP 协议&#xff1a;网络通信的基石 导语 你是否曾好奇&#xff0c;现代互联网是如何实现全球设备之间的高速、稳定和可靠通信的&#xff1f;无论是浏览网页、发送电子邮件&#xff0c;还是进行视频通话&#xff0c;背后都离不开 TCP/IP 协议 的支撑。作为互联网…...

图数据库 | 19、高可用分布式设计(下)

相信大家对分布式系统设计与实现的复杂性已经有了一定的了解&#xff0c;本篇文章对分布式图数据库系统中最复杂的一类系统架构设计进行探索&#xff0c;即水平分布式图数据库系统&#xff08;这个挑战也可以泛化为水平分布式图数据仓库、图湖泊、图中台或任何其他依赖图存储、…...

【2024年华为OD机试】 (C卷,200分)- 反射计数(Java JS PythonC/C++)

一、问题描述 题目解析 题目描述 给定一个包含 0 和 1 的二维矩阵&#xff0c;一个物体从给定的初始位置出发&#xff0c;在给定的速度下进行移动。遇到矩阵的边缘时会发生镜面反射。无论物体经过 0 还是 1&#xff0c;都不影响其速度。请计算并给出经过 t 时间单位后&#…...

【微服务】SpringCloud 1-9章

1从Boot和Cloud版本选型开始说起 1.1Springboot版本选择 1.1.1git源码地址 https://github.com/spring-projects/spring-boot/releases/ 1.1.2官网看Boot版本 1.1.3SpringBoot3.0崛起 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes …...