23种设计模式之装饰者模式
深入理解装饰者模式
- 一、装饰者模式简介
- 1.1 定义
- 1.2 模式类型
- 1.3 主要作用
- 1.4 优点
- 1.5 缺点
- 二、模式动机
- 三、模式结构
- 四、 装饰者模式的实现
- 4.1 组件接口
- 4.2 具体组件
- 4.3 装饰者抽象类
- 4.4 具体装饰者
- 4.5 使用装饰者模式
- 4.6 输出结果:
- 五、 应用场景
- 5.1 图形用户界面
- 5.2 数据流处理
- 5.3 日志功能
- 5.4 监控和计数
- 六、总结

一、装饰者模式简介
1.1 定义
装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地向对象添加新的功能,而不改变其结构和实现。装饰者模式通过组合来实现功能的扩展,它将功能划分成单一职责的类,并在需要时动态地组合这些功能实例化对象。
根据《设计模式:可复用面向对象软件的基础》一书的定义,装饰者模式是:
动态地给对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活。
1.2 模式类型
结构型
1.3 主要作用
- 扩展功能:允许在运行时动态地给对象添加新的功能,而不需要修改对象的结构。这有助于遵循
OCP原则。 - 灵活性和可重用性:装饰者模式通过创建装饰类来包裹原始对象,并在装饰类中添加功能,这样可以灵活组合不同的装饰器以达到不同的功能组合,同时原始类和装饰类都可以独立复用。
- 简化复杂度:对于有大量可选功能的对象,如果使用继承来实现每种可能的功能组合,会导致类的数量爆炸式增长。装饰者模式通过组合而非继承的方式来添加功能,大大减少了类的数量,简化了系统的复杂度。
- 保持接口一致性:装饰者模式保持了被装饰对象的接口一致,客户端代码可以透明地使用装饰后的对象,无需关心是否以及如何被装饰,这有利于代码的维护和扩展。
- 易于管理对象的责任:每个装饰者都负责单一职责,即添加特定的功能,这使得对象的责任更加清晰,便于管理和调试。
1.4 优点
- 灵活性高:可以在运行时任意组合装饰者,动态地扩展对象功能。
- 符合单一职责原则:每个装饰者类只负责增加一种功能,类的职责更加单一。
- 降低类复杂度:相比通过继承扩展功能,装饰者模式避免了大量的子类生成,从而减少类的复杂度。
1.5 缺点
- 对象数量增多:由于装饰者和被装饰者都是对象,这会增加系统中对象的数量,增加管理成本。
- 依赖过多:容易产生过多的小型对象,增加系统复杂性,理解和维护变得更加困难。
二、模式动机
装饰者模式的主要动机是应对以下几个问题:
- 避免类爆炸:通过继承添加新功能会导致子类数量激增,维护起来十分困难。
- 灵活组合功能:继承的组合方式是静态的,不够灵活。装饰者模式允许动态地组合功能。
- 单一职责原则:通过将功能分解到不同的装饰类中,装饰者模式使每个类的职责更加单一,代码更易读易维护。
三、模式结构

装饰者模式通常涉及以下几个角色:
- Component(抽象组件):定义一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(具体组件):实现
Component接口的具体对象,可以给这些对象添加一些职责。 - Decorator(装饰者抽象类):继承
Component接口,通常持有一个Component对象的引用,并定义一个与Component接口一致的接口。 - ConcreteDecorator(具体装饰者):扩展
Decorator类的具体装饰者,负责向组件添加新的职责。
四、 装饰者模式的实现
我们将以一个具体的咖啡示例来介绍装饰者模式的实现。在这个例子中,我们有一个基本的咖啡对象,可以动态地添加不同的配料(如牛奶和糖)。
4.1 组件接口
// Java实现
public interface Coffee {double cost();String getDescription();
}
4.2 具体组件
public class SimpleCoffee implements Coffee {public double cost() {return 5.0;}public String getDescription() {return "Simple Coffee";}
}
4.3 装饰者抽象类
public abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}public double cost() {return coffee.cost();}public String getDescription() {return coffee.getDescription();}
}
4.4 具体装饰者
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}public double cost() {return super.cost() + 1.5;}public String getDescription() {return super.getDescription() + ", Milk";}
}public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}public double cost() {return super.cost() + 0.5;}public String getDescription() {return super.getDescription() + ", Sugar";}
}
4.5 使用装饰者模式
public class CoffeeShop {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + " Cost: $" + coffee.cost());}
}
4.6 输出结果:
Simple Coffee Cost: $5.0
Simple Coffee, Milk Cost: $6.5
Simple Coffee, Milk, Sugar Cost: $7.0
五、 应用场景

5.1 图形用户界面
在图形用户界面(GUI)框架中,装饰者模式广泛应用于实现各种控件的装饰功能。控件如按钮、文本框等可以用不同的装饰者类装饰来添加多种新功能,如滚动条、边框等。例如,Java Swing框架中的JComponent类就是使用类似装饰者模式的理念实现的。
5.2 数据流处理
在数据流处理框架中,输入输出流是装饰者模式的另一个经典应用。Java的I/O流设计就是实现装饰者模式的一个优秀示例,如FileInputStream、BufferedInputStream和DataInputStream等通过装饰者模式组合,实现了灵活而强大的数据流操作功能。
5.3 日志功能
日志记录功能的实现也是装饰者模式的理想应用场景。例如,传统的日志记录器Logger可以通过装饰者模式添加不同的日志处理和记录策略,如格式化日志、输出到文件、发送电子邮件等。
5.4 监控和计数
在监控系统中,可以动态地为程序添加计数器、性能监控器等功能,以增强对系统运行状态的了解。
六、总结
装饰者模式是一种强大的设计模式,它提供了一种灵活、可扩展的方式来动态地为对象添加新功能。通过这一模式,我们可以在不修改已有类代码的情况下,灵活地扩展系统功能,符合开闭原则和单一职责原则。无论是在GUI编程中、日志功能增强,还是在数据流处理以及监控系统中,装饰者模式都能发挥重要作用。
相关文章:
23种设计模式之装饰者模式
深入理解装饰者模式 一、装饰者模式简介1.1 定义1.2 模式类型1.3 主要作用1.4 优点1.5 缺点 二、模式动机三、模式结构四、 装饰者模式的实现4.1 组件接口4.2 具体组件4.3 装饰者抽象类4.4 具体装饰者4.5 使用装饰者模式4.6 输出结果: 五、 应用场景5.1 图形用户界面…...
数据结构--单链表实现
欢迎光顾我的homepage 前言 链表和顺序表都是线性表的一种,但是顺序表在物理结构和逻辑结构上都是连续的,但链表在逻辑结构上是连续的,而在物理结构上不一定连续;来看以下图片来认识链表与顺序表的差别 这里以动态顺序表…...
2024攻防演练:亚信安全推出MSS/SaaS短期定制服务
随着2024年攻防演练周期延长的消息不断传出,各参与方将面临前所未有的挑战。面对强大的攻击队伍和日益严格的监管压力,防守单位必须提前进行全面而周密的准备和部署。为应对这一形势,亚信安全特别推出了为期三个月的MSS/SaaS短期订阅方案。该…...
基于java+springboot+vue实现的在线课程管理系统(文末源码+Lw)236
摘要 本文首先介绍了在线课程管理系统的现状及开发背景,然后论述了系统的设计目标、系统需求、总体设计方案以及系统的详细设计和实现,最后对在线课程管理系统进行了系统检测并提出了还需要改进的问题。本系统能够实现教师管理,科目管理&…...
每日一更 EFK日志分析系统
需要docker和docker-compose环境 下面时docker-compose.yaml文件 [rootnode1 docker-EFK]# cat docker-compose.yaml version: 3.3services:elasticsearch:image: "docker.elastic.co/elasticsearch/elasticsearch:7.17.5"container_name: elasticsearchrestart: …...
python类继承和类变量
Python一些类继承和实例变量的使用 定义基类 class APIException:code 500msg "Sorry, error"error_code 999def __init__(self, msgNone):print("APIException init ...")def error_400(self):pass复用基类的属性值 class ClientTypeError(APIExcept…...
js 随机生成整数
随机生成一个唯一的整数 id export const randomId () > { return Date.now() Math.floor(Math.random() * 10000) } 生成随机ID的方法 // 随机生成0 - 9999 export const randomId ()> { return Math.floor(Math.random() * 10000).toString() } // 随机生成0-999之…...
深入Django(七)
Django的数据库迁移系统 引言 在前六天的教程中,我们介绍了Django的基本概念、模型、视图、模板、URL路由和表单系统。今天,我们将讨论Django的数据库迁移系统,它是管理和跟踪数据库变化的关键组件。 Django数据库迁移概述 Django的数据库…...
【区分vue2和vue3下的element UI Steps 步骤条组件,分别详细介绍属性,事件,方法如何使用,并举例】
在 Vue 2 和 Vue 3 中,Element UI(针对 Vue 2)和 Element Plus(针对 Vue 3)提供了 Steps 步骤条组件,用于展示当前操作的进度步骤。虽然这两个库都提供了步骤条组件,但它们在属性、事件和方法的…...
uni-app x 跨平台开发框架
目录 uni-app x 是什么 和Flutter对比 uts语言 uvue渲染引擎 组合式API的写法 选项式API写法 页面生命周期 API pages.json全局配置文件 总结 uni-app x 是什么 uni-app x,是下一代 uni-app,是一个跨平台应用开发引擎。 uni-app x 是一个庞…...
YOLOv8模型调参---数据增强
目录 1.数据预处理 2.数据增强 2.1 数据增强的作用 2.2 数据增强方式与适用场景 2.2.1离线增强(Offline Augmentation) 2.2.2 在线增强(Online Augmentation) 3. 数据增强的具体方法 4. YOLOv8的数据增强 4.1 YOLOv8默认…...
【Nginx】docker运行Nginx及配置
Nginx镜像的获取 直接从Docker Hub拉取Nginx镜像通过Dockerfile构建Nginx镜像后拉取 二者区别 主要区别在于定制化程度和构建过程的控制: 直接拉取Nginx镜像: 简便性:直接使用docker pull nginx命令可以快速拉取官方的Nginx镜像。这个过程…...
tensorflow和numpy的版本
查看cuda版本 dpkg -l | grep cuda i libcudart11.0:amd64 11.5.117~11.5.1-1ubuntu1 amd64 NVIDIA CUDA Runtime Library ii nvidia-cuda-dev:amd64 11.5.1-1ubuntu1 …...
二维Gamma分布的激光点云去噪
目录 1、Gamma 分布简介2、实现步骤 1、Gamma 分布简介 Gamma 分布在合成孔径雷达( Synthetic Aperture Radar,SAR) 图像分割中具有广泛应用,较好的解决了SAR 图像中相干斑噪声对图像分割的影响。采用二维Gamma 分布对…...
鸿蒙笔记导航栏,路由,还有axios
1.导航组件 导航栏位置可以调整,导航栏位置 Entry Component struct t1 {build() {Tabs(){TabContent() {Text(qwer)}.tabBar("首页")TabContent() {Text(发现内容)}.tabBar(发现)TabContent() {Text(我的内容)}.tabBar("我的")}// 做平板适配…...
Spring 框架中都用到了哪些设计模式:单例模式、策略模式、代理模式
Spring 框架是一个功能强大的企业级应用开发框架,它使用了多种设计模式来提高代码的可维护性、可扩展性和可重用性。以下是 Spring 框架中常见的几个设计模式,并简要说明它们的应用场景: 1. 单例模式(Singleton Pattern) 定义:确保一个类只有一个实例,并提供全局访问点…...
阶段总结——基于深度学习的三叶青图像识别
阶段总结——基于深度学习的三叶青图像识别 文章目录 一、计算机视觉图像分类系统设计二、训练模型2.1. 构建数据集2.2. 网络模型选择2.3. 图像数据增强与调参2.4. 部署模型到web端2.5. 开发图像识别小程序 三、实验结果3.1. 模型训练3.2. 模型部署 四、讨论五、参考文献&#…...
深度解析Java世界中的对象镜像:浅拷贝与深拷贝的奥秘与应用
在Java编程的浩瀚宇宙中,对象拷贝是一项既基础又至关重要的技术。它直接关系到程序的性能、资源管理及数据安全性。然而,提及对象拷贝,不得不深入探讨其两大核心类型:浅拷贝(Shallow Copy)与深拷贝…...
Python | Leetcode Python题解之第218题天际线问题
题目: 题解: class Solution:def getSkyline(self, buildings: List[List[int]]) -> List[List[int]]:buildings.sort(keylambda bu:(bu[0],-bu[2],bu[1]))buildings.append([inf,inf,inf])heap [[-inf,-inf,-inf]]ans []for l,r,h in buildings:i…...
使用Spring Boot构建RESTful API
使用Spring Boot构建RESTful API 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将深入探讨如何使用Spring Boot构建RESTful API。通过这篇…...
AlphaFold 3终极指南:掌握Jackhmmer与HMMER提升蛋白质结构预测精度
AlphaFold 3终极指南:掌握Jackhmmer与HMMER提升蛋白质结构预测精度 【免费下载链接】alphafold3 AlphaFold 3 inference pipeline. 项目地址: https://gitcode.com/gh_mirrors/alp/alphafold3 你是否在蛋白质结构预测项目中遇到MSA生成效率低下的瓶颈&#x…...
C++中显示与隐式加载dll的使用与区别
一、什么是 DLL?DLL(Dynamic Link Library) 是 Windows 下的动态链接库,包含可被多个程序共享的函数、资源或类。使用 DLL 可以实现代码复用、模块化设计和插件机制。在 C 中,调用 DLL 中的函数有两种主要方式…...
新手也能懂的SSRF漏洞实战:用iwebsec靶场复现文件读取与内网探测
从零开始掌握SSRF漏洞:iwebsec靶场实战指南1. 认识SSRF漏洞的本质想象一下,你正在一家高档餐厅点餐,服务员承诺可以帮你从任何地方获取食材——包括隔壁竞争对手的厨房。SSRF(Server-Side Request Forgery)漏洞就像这个…...
告别虚拟机卡顿:在Windows 11的WSL2里搞定Lichee Nano交叉编译环境
告别虚拟机卡顿:在Windows 11的WSL2里搞定Lichee Nano交叉编译环境 对于嵌入式开发者来说,配置开发环境往往是个令人头疼的问题。传统虚拟机方案虽然能提供完整的Linux体验,但资源占用高、启动慢、与宿主系统交互不便等问题一直困扰着开发者。…...
SkillVLA:通过技能复用应对双-臂操纵中的组合多样性
26年3月来自新加坡国立、北京中关村学院、上海创新研究院、上海AI实验室、上海交大和复旦的论文“SkillVLA: Tackling Combinatorial Diversity in Dual-Arm Manipulation via Skill Reuse”。 视觉-语言-动作(VLA)模型近期取得的进展,已充分…...
智慧无人机巡检-无人机可见光红外数据集 无人机多模态检测数据集 红外与可见光检测数据集
智慧无人机巡检-无人机可见光红外数据集,已完成标注,可导出各种常用数据集,yolo,voc,coco等格式。可见光33000张,红外16100张,目标一张一个 无人机可见光红外目标数据集项目详细信息数据集名称无…...
航空航天为什么离不开高强镁合金?国产替代到哪一步了
飞机每减重一千克,全年大约节省四千两百美元的燃油费用——这是航空工程师熟悉的经验值。在商业航空领域,这个数字还只是财务账;在战斗机、导弹和卫星的世界里,减重的收益被换算成更远的航程、更大的载荷、更高的机动性࿰…...
CPU架构启发的智能仓储布局优化实践
1. 仓库布局优化的核心挑战与创新机遇在物流仓储领域,拣货环节通常占据运营成本的55%-65%,而其中约50%的时间消耗在无效行走路径上。传统矩形仓库布局虽然易于规划和施工,但其正交的通道设计导致拣货员需要频繁进行90度转向,这种&…...
如何在3分钟内为任何活动搭建专业级滚动抽奖系统?Magpie-LuckyDraw全平台开源方案深度解析
如何在3分钟内为任何活动搭建专业级滚动抽奖系统?Magpie-LuckyDraw全平台开源方案深度解析 【免费下载链接】Magpie-LuckyDraw 🏅A fancy lucky-draw tool supporting multiple platforms💻(Mac/Linux/Windows/Web/Docker) 项目地址: https…...
企业云盘签章技术方案:从数字签名原理到工程落地
背景 电子签章在企业云盘中的落地,不只是一个"上传盖章图片"的功能实现。本质上,它是一套涉及数字签名、PKI基础设施、文档完整性校验的综合性技术方案。本文从技术选型角度,说清楚企业云盘内置签章需要解决哪些问题、主流实现方案…...
