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

设计模式学习之——装饰者模式

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地向一个现有的对象添加新的行为,同时又不改变其结构。

一、定义与特点

  • 定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。

  • 特点

    • 结构型模式:装饰者模式关注于对象的组合以及如何通过组合来实现新的功能。
    • 动态扩展:通过装饰者模式,可以在不修改原有类代码的情况下,动态地向对象添加新的行为。
    • 透明性:装饰后的对象仍然可以被当作原有类型的对象来使用,客户端代码不需要知道对象是否被装饰过。

二、关键角色与职责

  • Component(抽象构件)

    • 定义一个接口或抽象类,声明了在具体构件中实现的业务方法。
    • 它是具体构件和抽象装饰类的共同父类,引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
  • ConcreteComponent(具体构件)

    • 实现了Component接口或抽象类的具体类,定义了具体的构件对象。
    • 实现了在Component中声明的方法,装饰器可以给它增加额外的职责(方法)。
  • Decorator(抽象装饰类)

    • 继承自Component接口或抽象类,用于给具体构件增加职责。
    • 维护一个指向Component对象的引用,通过该引用可以调用装饰之前构件对象的方法。
    • 需要在子类中实现具体的装饰行为。
  • ConcreteDecorator(具体装饰类)

    • 继承自Decorator抽象类,负责向构件添加新的职责。
    • 每一个具体装饰类都定义了一些新的行为,可以调用在Decorator中定义的方法,并可以增加新的方法用以扩充对象的行为。

三、运行机制

  • 创建具体构件对象:首先创建一个具体构件对象,这是需要被装饰的原始对象。
  • 创建装饰器对象:接着创建一个或多个装饰器对象,通过构造函数将具体构件对象传入装饰器对象。
  • 调用方法:当调用装饰后对象的方法时,装饰器对象会先调用其所持有的具体构件对象的方法,然后再执行自己定义的额外行为。

四、适用场景

  • 功能扩展:需要为一个类扩展功能,为其添加额外的职责。
  • 动态添加行为:需要在运行时动态地向对象添加新的行为,而不需要修改其类定义。
  • 避免子类爆炸:通过装饰者模式可以避免通过继承来扩展功能所导致的子类数量过多的问题。

五、优缺点

  • 优点

    • 灵活性:提供了比继承更加灵活的功能扩展方式。
    • 可扩展性:可以通过组合不同的装饰器来创建具有不同行为的新对象。
    • 透明性:装饰后的对象仍然可以被当作原有类型的对象来使用。
  • 缺点

    • 复杂性:会产生很多的小对象,增加了系统的复杂性。
    • 排错困难:对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

六、代码示例

示例一:Java中的IO流

以Java中的IO流为例,InputStream和OutputStream是最基本的抽象构件,而各种FilterInputStream和FilterOutputStream就是具体的装饰器,它们可以实现各种不同的IO流处理功能,如缓冲、压缩、加密等。

// 抽象构件
InputStream input = new FileInputStream("example.txt");// 具体装饰器(缓冲流)
BufferedInputStream bufferedInput = new BufferedInputStream(input);// 再次装饰(数据输入流)
DataInputStream dataInput = new DataInputStream(bufferedInput);// 使用装饰后的对象读取数据
while (dataInput.available() != 0) {System.out.print((char) dataInput.readByte());
}
dataInput.close();

在这个例子中,FileInputStream是具体构件,BufferedInputStreamDataInputStream是具体装饰器,它们依次对输入流进行了缓冲和数据处理功能的装饰。

示例二:咖啡制作 

在咖啡制作系统中,一杯咖啡可以有多种调料(如糖、奶、奶油等)。通过装饰器模式,可以动态地为咖啡添加不同的调料,而不需要创建大量的子类来表示不同调料组合的咖啡

   interface Coffee {double cost();}class SimpleCoffee implements Coffee {@Overridepublic double cost() {return 1.0;}}abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}}class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return coffee.cost() + 0.5;}}

综上所述,装饰者模式是一种强大且灵活的设计模式,它允许我们在不修改原有类代码的情况下动态地向对象添加新的行为。然而,在使用时也需要注意其可能带来的系统复杂性和排错困难等问题。

相关文章:

设计模式学习之——装饰者模式

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地向一个现有的对象添加新的行为,同时又不改变其结构。 一、定义与特点 定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者…...

【Vulkan入门】10-CreatePipeline

目录 先叨叨Git信息关键代码TestPipeline::Initialize() 编译运行 先叨叨 到上篇为止已经创建了FrameBuffer和RenderPass。建立Pipeline的先决条件已经具备。本篇就来创建Pipeline。 Git信息 repository: https://gitee.com/J8_series/easy-car-uitag: 10-CreatePipelineurl…...

C++11 (一)

一、 C11的发展历史 C11是C 的第二个主要版本,并且是从 C98 起的最重要更新。 它引入了大量更改,标准化了既有实践,并改进了对C程序员可用的抽象。在它最终由IS0在2011年8月12日采纳前,人们曾使用名称“C0x”,因为它曾…...

系统性能优化

一、概述 性能优化的目标:是提高系统或应用程序的响应时间、吞吐量、cpu、内存、磁盘IO、网络、流量、JVM、Tomcat、DB等方面的性能指标。 性能优化需要有一些技巧:对于整个产品或项目而言,比如可以从前端优化、后端优化、架构优化、高并发…...

IMX6ULL开发板挂载 Ubuntu 的 NFS 目录,并以交叉编译得到的hello程序进行测试

首先参考博文 https://blog.csdn.net/wenhao_ir/article/details/144404637 使得IMX6ULL开发板、PC机上的USB网卡、VMware中的Ubuntu能互相Ping 通 然后开始将Ubuntu 的 NFS 目录挂载到Ubuntu中。 为什么挂载? 答:其实是把 Ubuntu中的某个目录通过NFS网…...

Xcode模拟器运行报错:The request was denied by service delegate

Xcode模拟器运行报错:The request was denied by service delegate 造成的原因: (1)新的苹果M系列芯片的Mac电脑 (2)此电脑首次安装启动Xcode的应用程序 (3)此电脑未安装Rosetta 2 解决方法: …...

ubuntu18.04配置实时内核

ubuntu系统:18.04 当前内核:5.4.0-84-generic 待安装实时内核: 5.6.19-rt11 1、查看当前版本 uname -r 2、下载内核与补丁 一种方式从官网自己下载 官方内核下载地址官方补丁下载地址阿里镜像内核下载地址(速度快&#xff0…...

Unity中Mesh重叠顶点合并参考及其应用

在Unity中,如果将一个模型文件(比如从max里面导出一个fbx文件)导入到编辑器中之后,Unity会把所有在原来在面列表中公用的顶点复制一份,保证每个三角形使用的顶点都是单独的,不与其它三角形共用顶点&#xf…...

倚光科技助力自由曲面设计与加工

近年来,自由曲面因其在光学、汽车、航空航天等领域的广泛应用,受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜,能够在光学系统中实现更加精确的光线控制,优化像差校正,并且在满足功能需求…...

PWM调节DCDC参数计算原理

1、动态电压频率调整DVFS SOC芯片的核电压、GPU电压、NPU电压、GPU电压等,都会根据性能和实际应用场景来进行电压和频率的调整。 即动态电压频率调整DVFS(Dynamic Voltage and Frequency scaling),优化性能和功耗。 比如某SOC在…...

[Pro Git#3] 远程仓库 | ssh key | .gitignore配置

目录 1. 分布式版本控制系统的概念 2. 实际使用中的“中央服务器” 3. 远程仓库的理解 4. 新建远程仓库 5. 克隆远程仓库 6. 设置SSH Key 实验 一、多用户协作与公钥管理 二、克隆后的本地与远程分支对应 三、向远程仓库推送 四、拉取远程仓库更新 五、配置Git忽略…...

Freertos任务切换

一、操作系统进行任务切换的时机: 采用信号量实现任务的互斥: 二、FreeRTOS 任务切换场合 PendSV 中断的时候提到了上下文(任务)切换被触发的场合: ● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。 1、执行系统调用 执行系统…...

go开发中interface和方法接收器的使用

Go 语言中的接口和方法接收器学习 Go 中的 interface 就像是一个神奇的魔法杖,能让你轻松地将不同的类型拉到同一个阵营里。与其他语言的接口不同,Go 的接口无需显式声明“我实现了你”,只要你满足了接口规定的方法,Go 就会自动认…...

vue3-tp8-Element:对话框实现

效果 参考框架 Dialog 对话框 | Element Plus 具体实现 一、建立view页面 /src/views/TestView.vue 二、将路径写入路由 /src/router/index.js import { createRouter, createWebHistory } from vue-router import HomeView from ../views/HomeView.vueconst router create…...

高中数学:随机变量-正态分布

文章目录 一、连续性随机变量二、大致图像三、正态分布图像及解析式图像特点均值与方差公式正态分布各区域概率 一、连续性随机变量 二、大致图像 三、正态分布图像及解析式 图像特点 均值与方差公式 正态分布各区域概率...

游戏引擎学习第47天

仓库: https://gitee.com/mrxiao_com/2d_game 昨天我们花了一点时间来修复一个问题,但基本上是在修复这个问题的过程中,我们决定添加一个功能,那就是在屏幕上控制多个实体。所以如果我有一个手柄,我可以添加另一个角色&#xff0…...

Git 仓库托管教程

git远程仓库 常用的远程仓库-->托管服务:github、码云、gitlab等 github需要魔法上网,速度较慢因为在国外且仅仅支持Git,如果不是Git项目是不支持的;码云--gitee国内的代码托管平台,服务器在国内速度快一些&#…...

基于51单片机的简易时钟/定时器闹钟proteus仿真

地址: https://pan.baidu.com/s/1uez4cwZuXpchmihmRqnLEg 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectro…...

Jackson @JsonProperty 注解

1. 概述 Jackson 是一个流行的Java库,用于将Java对象转换为JSON格式以及从JSON反序列化回Java对象。一种常见的需求是在序列化为JSON或从JSON反序列化时自定义字段的命名。Jackson 的 JsonProperty 注解正好满足了这一需求。 JsonProperty 注解概览 JsonProperty…...

【Excel学习记录】02-单元格格式设置

1.单元格格式工具美化表格 单元格格式位置 选中单元格,右键→设置单元格格式 合并居中 跨越合并 字体类型、大小、颜色、填充底纹、边框 斜线 软回车:alt enter 格式刷 2.单元格数字格式 格式不影响数值,只是展示形式 日期本质也是数…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制&#xff0…...

Robots.txt 文件

什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

【HTTP三个基础问题】

面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...