java设计模式学习之【装饰器模式】
文章目录
- 引言
- 装饰器模式简介
- 定义与用途
- 实现方式
- 使用场景
- 优势与劣势
- 装饰器模式在Spring中的应用
- 画图示例
- 代码地址
引言
在日常生活中,我们常常对基本事物添加额外的装饰以增强其功能或美观。例如,给手机加一个保护壳来提升其防护能力,或者在房间里添加装饰品以提升美观。这种增加附加功能的做法在软件开发中也有所体现,特别是在装饰器模式中。装饰器模式允许我们在不改变对象自身的基础上,为对象添加新的功能。这种模式在软件开发中非常有用,特别是当我们希望动态地、透明地为对象增加职责时。
装饰器模式简介
定义与用途
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许用户在不改变对象自身的基础上向一个对象添加新的功能。在这种模式中,我们通过创建一个包装对象,也称为装饰器,来包裹真实对象。
实现方式
实现装饰器模式通常包括以下几个关键组件:
- 抽象组件(Component): 定义了一个对象接口,可以给这些对象动态地添加职责。
- 具体组件(Concrete Component): 定义了抽象组件的具体实现,即被装饰的对象。
- 抽象装饰器(Decorator): 持有一个组件(Component)对象的引用,并定义了符合组件接口的接口。
- 具体装饰器(Concrete Decorator): 实现抽象装饰器的接口,并添加额外的功能。
使用场景
装饰器模式非常适合以下场景:
- 当需要扩展一个类的功能时。
- 当需要动态地为对象增加功能,且这些功能可以再动态地撤销。
- 当扩展类的功能比创建子类更有弹性时。
例如:
-
图形用户界面组件装饰:在图形用户界面中,可以用装饰器模式给基本组件(如按钮、文本框等)动态添加一些附加功能,比如边框、阴影、鼠标悬停效果等。
-
数据流增强:在数据流处理中,如文件流、网络流等,装饰器模式可以用来动态地添加新的功能,比如数据加密、压缩、缓冲等。
-
权限控制:在一些应用程序中,根据用户的权限级别动态地给对象添加不同的行为(例如,对基本功能的访问权限控制)。
-
性能监控:在性能监控和日志记录中,装饰器可以被用来在不更改原有类的基础上,为方法或对象添加日志记录和性能监控的功能。
-
动态添加属性或行为:在需要为对象动态添加属性或行为的场景,比如在游戏开发中给角色添加不同的技能或状态效果,装饰器模式提供了一种灵活的解决方案。
-
Web 服务中的中间件:在Web开发中,中间件可以看作是对HTTP请求或响应的装饰器,用于处理认证、日志记录、错误处理等。
优势与劣势
- 优势
增加对象功能: 装饰器模式提供了一种灵活的方式来增加对象的功能,与继承相比,这种方式更具灵活性。
动态扩展: 可以在运行时动态地添加或删除功能。
避免类爆炸: 减少了子类的数量,避免了类数量过多的问题。 - 劣势
增加系统复杂性: 添加装饰器可以使系统变得更加复杂,特别是当有很多层装饰时。
维护困难: 更复杂的代码意味着维护起来更困难。
装饰器模式在Spring中的应用
1. Spring AOP(面向切面编程)
Spring AOP是装饰器模式的一个经典应用例子。在Spring AOP中,切面(Aspect)可被视为装饰器,它们为业务逻辑(如服务层的方法)提供了附加功能(例如,事务管理、日志记录、安全性检查等),而不修改原有功能的代码。通过代理模式结合装饰器模式,Spring AOP在运行时动态地向对象添加额外的行为。2. Spring I/O资源抽象
在Spring的资源抽象(如Resource接口和其实现类)中,装饰器模式被用来增强基础资源对象(如文件系统资源、类路径资源等)的功能。例如,BufferedInputStream是Java I/O的一个装饰器,Spring结合使用这些装饰器以提供高效的数据访问。3. Spring MVC的视图技术集成
Spring MVC框架通过使用装饰器模式,可以将不同的视图技术(如JSP、Freemarker、Thymeleaf)无缝集成到同一模型中。控制器返回模型和视图对象,而实际的视图可以是任何实现了View接口的对象,这些视图对象可以是装饰过的对象,提供了额外的渲染逻辑。4. Spring Security的身份验证和授权
Spring Security使用装饰器模式来增强或修改用户的身份验证对象(如UserDetails),并在安全上下文中添加额外的安全属性。这允许开发者在不改变现有身份验证逻辑的基础上,轻松地添加或改变认证信息。5. Spring的事务管理
在Spring的声明式事务管理中,装饰器模式被用于动态地添加事务管理逻辑到业务逻辑上。例如,通过使用@Transactional注解,Spring在运行时创建一个代理对象(装饰器),围绕着原始的bean实例,以提供事务管理的功能。6. Spring的数据访问集成
Spring的数据访问集成(如JdbcTemplate、HibernateTemplate等)也使用装饰器模式来提供额外的数据处理功能,比如异常翻译、资源管理等,而不改变原有数据访问逻辑。
画图示例

步骤 1: 创建图形一个接口。
public interface Shape {void draw();
}
步骤 2: 创建实现相同接口的具体类。
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("图形:矩形");}}
public class Circle implements Shape{@Overridepublic void draw() {System.out.println("图形:圆形");}}
步骤 3: 创建实现 Shape 接口的抽象装饰器类。
public abstract class ShapeDecorator implements Shape {protected Shape decoratedShape;public ShapeDecorator(Shape decoratedShape){this.decoratedShape = decoratedShape;}@Overridepublic void draw(){decoratedShape.draw();}}
步骤 4: 创建扩展 ShapeDecorator 类的具体装饰器类。给画图加上边框红边的功能
public class RedShapeDecorator extends ShapeDecorator{public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {decoratedShape.draw();setRedBorder(decoratedShape);}private void setRedBorder(Shape decoratedShape){System.out.println("边框颜色:红色");}}
步骤 5: 使用 RedShapeDecorator 来装饰 Shape 对象。
public class DecoratorPatternDemo {public static void main(String[] args) {Shape circle = new Circle();Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());System.out.println("带有普通边框的圆形");circle.draw();System.out.println("\n带有红色边框的圆形");redCircle.draw();System.out.println("\n带有红色边框的矩形");redRectangle.draw();}}

在这个具体示例中,展示的是如何使用装饰器模式为简单的形状对象(如圆形和矩形)添加新的功能(如设置边框颜色)。
代码地址
23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern
相关文章:
java设计模式学习之【装饰器模式】
文章目录 引言装饰器模式简介定义与用途实现方式 使用场景优势与劣势装饰器模式在Spring中的应用画图示例代码地址 引言 在日常生活中,我们常常对基本事物添加额外的装饰以增强其功能或美观。例如,给手机加一个保护壳来提升其防护能力,或者在…...
Ubuntu宝塔面板本地部署Emlog个人博客网站并远程访问【内网穿透】
文章目录 前言1. 网站搭建1.1 Emolog网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2.Cpolar稳定隧道(云端设置)2.3.Cpolar稳定隧道(本地设置) 3. 公网访问测试总结 前言 博客作为使…...
简述IO流的使用以及使用时需要注意的事项
Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍介绍IO流的使用以及使用时需要注意的事项以及部分理论知识 🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁 🍉博主收将持续更新学习记录获,友友们有任何问题可…...
西工大计算机学院计算机系统基础实验一(函数编写11~14)
稳住心态不要慌,如果考试周冲突的话,可以直接复制这篇博客和上一篇博客西工大计算机学院计算机系统基础实验一(函数编写1~10)-CSDN博客最后的代码,然后直接提交,等熬过考试周之后回过头再慢慢做也可以。 第…...
Spring 声明式事务
Spring 声明式事务 1.Spring 事务管理概述1.1 事务管理的重要性1.2 Spring事务管理的两种方式1.2.1 编程式事务管理1.2.2 声明式事务管理 1.3 为什么选择声明式事务管理 2. 声明式事务管理2.1 基本用法2.2 常用属性2.2.1 propagation(传播行为)2.2.2 iso…...
通达OA inc/package/down.php接口存在未授权访问漏洞
声明 本文仅用于技术交流,请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。 一. 产品简介 通达OA(Office Anywhere网络智能办公系统&am…...
数据库原理: 笛卡儿积
笛卡儿积(Cartesian Product)是集合论中的一个概念,也在数据库中的查询操作中经常使用。笛卡儿积是指两个集合(或更多集合)之间所有可能的组合。如果有两个集合A和B,它们的笛卡儿积记作A B,表示…...
docker安装配置prometheus+node_export+grafana
简介 Prometheus是一套开源的监控预警时间序列数据库的组合,Prometheus本身不具备收集监控数据功能,通过获取不同的export收集的数据,存储到时序数据库中。Grafana是一个跨平台的开源的分析和可视化工具,将采集过来的数据实现可视…...
【JavaScript】JS——Map数据类型
【JavaScript】JS——Map数据类型 什么是Map?特性Map与Object的比较 map的创建map的属性map相关方法map的遍历 什么是Map? 存储键值对的对象。 能够记住键的原始插入顺序任何值(对象或原始值)都可以作为键或值。 特性 Map中的一个键只能出现一次&am…...
【【FPGA的 MicroBlaze 的 介绍与使用 】】
FPGA的 MicroBlaze 的 介绍与使用 可编程片上系统(SOPC)的设计 在进行系统设计时,倘若系统非常复杂,采用传统 FPGA 单独用 Verilog/VHDL 语言进行开发的方式,工作量无疑是巨大的,这时调用 MicroBlaze 软核…...
PyQt pdf格式保存
参考文章 pyqt5:利用QFileDialog从本地选择图片\文本文档显示到label、保存图片\label文本到本地(附代码)_pyqt5中qfiledialog.getopenfileurl-CSDN博客 txt文件的打开与保存 def openTextFile(self): # 选择文本文件上传fd,fp QFileDialog.getOpen…...
微前端介绍
目录 微前端概念 微前端特性 场景演示 微前端方案 iframe 方案 qiankun 方案 micro-app 方案 EMP 方案 无界微前端 方案 无界方案 成本低 速度快 原生隔离 功能强大 总结 前言:微前端已经是一个非常成熟的领域了,但开发者不管采用哪个现…...
工业机器视觉megauging(向光有光)使用说明书(一,轻量级的visionpro)
机器视觉megauging(未名之光,向光有光)程序软件资源已经发布,欢迎下载尝新 8:11 2023/12/2 首先,既然觉得可以发表了,就发表。 其次,我这个人没写过什么软件使用说明书,既然走到这路…...
Java——面试:String 和 StringBuffer 的区别?
相同点: String 和 StringBuffer,它们可以储存和操作字符串, 即包含多个字符的字符数据。 String 和 StringBuffer 的区别有以下几点: 1.String 类提供了数值不可改变的字符串。而 StringBuffer 类提供的字符串进行修改。 当你知…...
图扑软件受邀出席高交会-全球清洁能源创新博览会
“相聚鹏城深圳,共享能源盛宴” 第二十五届中国国际高新技术成果交易会(简称“高交会”)于 11 月 15-18 日在深圳盛大开幕。高交会由商务部、科学技术部、工业和信息化部、国家发展改革委、农业农村部、国家知识产权局、中国科学院、中国工程院和深圳市人民政府共同…...
vue项目下npm或yarn下安装echarts多个版本
最近在大屏展示的时候,用到了百度的echarts图表库,看完效果图后,又浏览了一下echarts官网案例,大同小异。但是搬砖过程中发现实际效果和demo相差甚远,一番折腾发现,项目中安装的是echarts4.x版本࿰…...
在内网开发中使用Nginx代理来访问钉钉新版服务端API
如果你在内网开发中使用Nginx代理来访问钉钉新版服务端API,你可以在Nginx配置文件中进行相应的配置。 以下是一个简单的示例Nginx配置,用于将对指定URL的请求代理到钉钉服务端API: server { listen 80; server_name your_server_domain; l…...
机器学习算法如何进行特征重要性评估
特征重要性评估是机器学习中一种常用的方法,用于确定输入特征对模型预测的贡献程度。以下是几种常见的机器学习算法进行特征重要性评估的方法: 1 决策树算法(如随机森林和梯度提升树):决策树算法可以通过计算每个特征…...
运行启动vue项目报报错node: --openssl-legacy-provider is not allowed in NODE_OPTIONS解决
报错的问题就是package.json中的Scripts下的dev 解决方法就是要不升级你的应用代码,支持 新版本的node.js 要不就是删除SET NODE_OPTIONS--openssl-legacy-provider &&代码,如下代码即可正常运行起来...
网工学习5 交换机端口相关配置
交换机的接口属性默认支待一般网络环境,一般情况下是不需要对其接口进行设置的。在某些情况下需 要对其端口属性进行配置时,配置的对象主要有接口隔离、速率、双工等信息。 5.1 接口隔离设置 > 配置接口 GE0/0/1 和 GE0/0/2 的接口隔离功能…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
