java设计模式学习之【装饰器模式】

文章目录

  • 引言
  • 装饰器模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 装饰器模式在Spring中的应用
  • 画图示例
  • 代码地址

引言

在日常生活中,我们常常对基本事物添加额外的装饰以增强其功能或美观。例如,给手机加一个保护壳来提升其防护能力,或者在房间里添加装饰品以提升美观。这种增加附加功能的做法在软件开发中也有所体现,特别是在装饰器模式中。装饰器模式允许我们在不改变对象自身的基础上,为对象添加新的功能。这种模式在软件开发中非常有用,特别是当我们希望动态地、透明地为对象增加职责时。

装饰器模式简介

定义与用途

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许用户在不改变对象自身的基础上向一个对象添加新的功能。在这种模式中,我们通过创建一个包装对象,也称为装饰器,来包裹真实对象。

实现方式

实现装饰器模式通常包括以下几个关键组件:

  • 抽象组件(Component): 定义了一个对象接口,可以给这些对象动态地添加职责。
  • 具体组件(Concrete Component): 定义了抽象组件的具体实现,即被装饰的对象。
  • 抽象装饰器(Decorator): 持有一个组件(Component)对象的引用,并定义了符合组件接口的接口。
  • 具体装饰器(Concrete Decorator): 实现抽象装饰器的接口,并添加额外的功能。

使用场景

装饰器模式非常适合以下场景:

  • 当需要扩展一个类的功能时。
  • 当需要动态地为对象增加功能,且这些功能可以再动态地撤销。
  • 当扩展类的功能比创建子类更有弹性时。

例如:

  1. 图形用户界面组件装饰:在图形用户界面中,可以用装饰器模式给基本组件(如按钮、文本框等)动态添加一些附加功能,比如边框、阴影、鼠标悬停效果等。

  2. 数据流增强:在数据流处理中,如文件流、网络流等,装饰器模式可以用来动态地添加新的功能,比如数据加密、压缩、缓冲等。

  3. 权限控制:在一些应用程序中,根据用户的权限级别动态地给对象添加不同的行为(例如,对基本功能的访问权限控制)。

  4. 性能监控:在性能监控和日志记录中,装饰器可以被用来在不更改原有类的基础上,为方法或对象添加日志记录和性能监控的功能。

  5. 动态添加属性或行为:在需要为对象动态添加属性或行为的场景,比如在游戏开发中给角色添加不同的技能或状态效果,装饰器模式提供了一种灵活的解决方案。

  6. 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 {

    @Override
    public void draw() {
        System.out.println("图形:矩形");
    }

}
public class Circle implements Shape{

    @Override
    public void draw() {
        System.out.println("图形:圆形");
    }

}

步骤 3: 创建实现 Shape 接口的抽象装饰器类。

public abstract class ShapeDecorator implements Shape {

    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape){
        this.decoratedShape = decoratedShape;
    }

    @Override
    public void draw(){
        decoratedShape.draw();
    }

}

步骤 4: 创建扩展 ShapeDecorator 类的具体装饰器类。给画图加上边框红边的功能

public class RedShapeDecorator extends ShapeDecorator{

    public RedShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

    @Override
    public 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/224328.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

fastapi.templating与HTMLResponse

要声明一个模板对象,应将存储html模板的文件夹作为参数提供。在当前工作目录中,我们将创建一个 “templates “目录。 templates Jinja2Templates(directory“templates”) 我们现在要把这个页面的HTML代码渲染成HTMLResponse。让我们修改一下hello()函…

软考高项第四版五组十域表+ITTO背诵笔记及助记

基于第四版做的笔记,助记是自己编的 还是得靠理解记忆,下面是文档,也用anki制作了记忆卡片,需要的可以自行导入卡包

使用NimoShake将数据从AWS DynamoDB迁移至阿里云MongoDB

本文介绍从AWS DynamoDB到阿里云MongoDB的迁移框架。 它概述了以下步骤: 在阿里云上配置云数据库MongoDB版并应用公网终端节点在 AWS EC2 上安装 Nimoshake将AWS EC2访问阿里云MongoDB版列入白名单配置 Nimoshake 并开始迁移过程验证目标数据库上的增量数据 1. 创…

有什么可视化数据管理工具?

有什么可视化数据管理工具? 相信大家对数据分析并不陌生。数据可视化不仅可以使得数据更加直观、易于理解,而且可以帮助用户发现数据中的潜在规律和趋势。 但是,对于不熟悉编程的用户来说,如何将枯燥的大数据转化为可视化的图和…

苹果ios的系统app应用WebClip免签应用开源及方式原理

在移动设备上,为了方便访问我们经常使用的网站或服务,我们经常会希望将其添加到主屏幕上,以便快速启动。虽然我们可以通过使用浏览器书签实现这一目标,但添加一个图标到主屏幕上,使得它看起来与原生App无异&#xff0c…

数字工厂时代,如何实现3D数据访问与发布、WEB大模型可视化?

Tech Soft 3D的HOOPS 3D CAD SDK为现代工厂工作流程奠定了基础,通过最快、最准确的CAD数据访问和动态3D可视化支持数字孪生、机器人仿真、设计、流程和规划、IIoT和操作辅助应用程序。 本文将和您详细探讨。如何利用HOOPS技术来增强您的应用程序。 HOOPS_HOOPS试…

点滴生活记录1

2023/10/10 今天骑小电驴上班,带着小鸭子一起。路上的时候,我给小鸭子说,你要帮我看着点路,有危险的时候提醒我,也就刚说完没几分钟,一个没注意,直接撞到一个拦路铁墩子上,车子连人歪…

Django 模型操作(六)

Django通过Model操作数据库, 不管你数据库的类型是MySql或者Sqlite, Django自动帮你生成相应数据库类型的SQL语句,所以不需要关注SQL语句和类型,对数据的操作Django帮我们自动完成。只要会写Model就可以了。 django使用对象关系映射 (Object Relational Mapping, 简称ORM)框…

Flink State 状态原理解析 | 京东物流技术团队

一、Flink State 概念 State 用于记录 Flink 应用在运行过程中,算子的中间计算结果或者元数据信息。运行中的 Flink 应用如果需要上次计算结果进行处理的,则需要使用状态存储中间计算结果。如 Join、窗口聚合场景。 Flink 应用运行中会保存状态信息到 …

清新脱俗的Notes主页

大家好,才是真的好。 作为Notes客户端重度用户,我个人非常喜欢Notes客户机,平时都在使用。对于另一些Notes用户,喜欢Notes的人非常喜欢,而且还知道它非常强大,可以进行很多定制化。 今天我们来讲的就是No…

【MATLAB】SSA+FFT+HHT组合算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 SSAFFTHHT组合算法是一种基于奇异谱分析(SSA)、快速傅里叶变换(FFT)和希尔伯特-黄变换(HHT)的组合算法。 其中&am…

【CentOS8】使用 Tomcat 部署 Java Web 项目(使用 sdkman)

文章目录 配置 Tomcat将 Tomcat 启动命令设置为 Linux 自定义服务给 Tomcat 设置管理员账号密码IDEA 打包 Java web 项目 我是使用 sdkman 下载的 jdk 和 tomcat,所以接下来的部署配置都是在 sdkman 构建的环境的。想要知道如何下载 sdkman 可以看看这篇文章 —…

操作符(原码反码补码)

目录 前言&#xff1a; 原反补码&#xff1a; 位操作符&#xff1a; &#xff06; &#xff5c; &#xff3e; &#xff5e; >> << 总结&#xff1a; 逻辑操作符 && || 其他操作符&#xff1a; sizeof -- () &#xff1f;&#xf…

数据仓库与数据挖掘复习资料

一、题型与考点[第一种] 1、解释基本概念(中英互译解释简单的含义)&#xff1b; 2、简答题(每个10分有两个一定要记住)&#xff1a; ① 考时间序列Time series(第六章)的基本概念含义解释作用&#xff08;序列模式挖掘的作用&#xff09;&#xff1b; ② 考聚类(第五章)重点考…

Redis7--基础篇7(哨兵sentinel)

1. 关于哨兵的介绍 1、监控redis运行状态&#xff0c;包括master和slave&#xff08;主从监控&#xff09; 2、哨兵可以将故障转移的结果发送给客户端&#xff08;消息通知&#xff09; 3、当master down机&#xff0c;能自动将slave切换成新master&#xff08;故障转移&#…

STM32——电动车报警器

项目设计 // 如果检测到 PA4 被拉低&#xff08;小偷偷车&#xff09;&#xff0c;并且警报模式打开 // 则将 PB7 拉低&#xff0c;继电器通电&#xff0c;喇叭一直响 // 如果检测到 PA5 被拉高&#xff08;按键 A 按下&#xff09;&#xff0c;设定为开启警报模式 // 则将…

Python计算方差

方差可以反应变量的离散程度&#xff0c;是因为它度量了数据点与均值的差异。方差是每个数据点与均值的差的平方和的平均值&#xff0c;它可以反映数据点在均值附近的分布情况。如果方差较小&#xff0c;说明数据点更加集中在均值附近&#xff0c;离散程度较小&#xff1b;如果…

什么是神经网络的超参数

1 引言 超参数在神经网络的设计和训练中起着至关重要的作用。它们是在开始训练之前设置的参数&#xff0c;与网络的结构、训练过程和优化算法有关。正确的超参数选择对于达到最优模型性能至关重要。 2 神经网络结构的超参数 层数&#xff08;Layers&#xff09;&#xff1a; 决…

基于STM32 IAP技术的物联网设备固件更新应用研究

本文将深入研究基于STM32 IAP技术的物联网设备固件更新应用。首先&#xff0c;我们会介绍物联网设备固件更新的重要性和挑战。然后&#xff0c;我们将详细讲解STM32 IAP技术的原理和实现方式。接下来&#xff0c;我们会通过一个代码示例演示如何使用STM32 IAP技术实现物联网设备…

搭建个人网盘应用Nextcloud

使用DNF管理软件包 1 使用winscp工具将openeuler-20.03-LTS-x86_64-dvd.iso上传至openeuler虚拟机的/root目录下&#xff0c;然后执行如下命令挂载ISO [rootopenEuler ~]# mount -o loop /root/openEuler-20.03-LTS-everything-x86_64-dvd.iso /mnt/2 添加软件源 [rootope…