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

news2025/2/26 5:00:46

文章目录

  • 引言
  • 装饰器模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 装饰器模式在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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里云磁盘在线扩容

我们从阿里云的控制面板中给硬盘扩容后结果发现我们的磁盘空间并没有改变 注意:本次操作是针对CentOS 7的 #使用df -h并没有发现我们的磁盘空间增加 #使用fdisk -l发现确实还有部分空间 运行df -h命令查看云盘分区大小。 以下示例返回分区&#xf…

Java的三种代理模式实现

代理模式的定义: Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。) 简单说,就是设置一个中间代理来控制访问原目标对象,达到增强原…

复杂gRPC之go调用go

1. 复杂的gRPC调用 我们使用了一个较为复杂的proto文件,这个文件的功能主要是用来定位的,详细内容可以看代码中的注解 syntax "proto3"; //指定生成的所属的package,方便调用 option go_package "./"; package route…

渗透测试——七、网站漏洞——命令注入和跨站请求伪造(CSRF)

渗透测试 一、命令注入二、跨站请求伪造(CSRF)三、命令注入页面之注人测试四、CSRF页面之请求伪造测试 一、命令注入 命令注入(命令执行) 漏洞是指在网页代码中有时需要调用一些执行系统命令的函数例如 system()、exec()、shell_exec()、eval()、passthru(),代码未…

B站缓存视频M4S合并MP4(js + ffmpeg )

文章目录 B站缓存视频转MP4(js ffmpeg )1、说明 2、ffmpeg2.1 下载地址2.2 配置环境变量2.3 测试2.4 转换MP4命令 3、处理程序 B站缓存视频转MP4(js ffmpeg ) 注意:这样的方式只用于个人之间不同设备的离线观看。请…

链式二叉树的创建及遍历(数据结构实训)

题目: 链式二叉树的创建及遍历 描述: 树的遍历有先序遍历、中序遍历和后序遍历。先序遍历的操作定义是先访问根结点,然后访问左子树,最后访问右子树。中序遍历的操作定义是先访问左子树,然后访问根,最后访问…

阿里云实时数据仓库HologresFlink

1. 实时数仓Hologres特点 专注实时场景:数据实时写入、实时更新,写入即可见,与Flink原生集成,支持高吞吐、低延时、有模型的实时数仓开发,满足业务洞察实时性需求。亚秒级交互式分析:支持海量数据亚秒级交…

单片机学习13——串口通信

单片机的通信功能: 实现单片机和单片机的信息交换,实现单片机和计算机的信息交换。 计算机通信是指计算机与外部设备或计算机与计算机之间的信息交换。 通信有并行通信和串行通信两种方式。 在多微机系统以及现在测控系统中信息的交换多采用串行通信方…

游戏盾的防御原理以及为什么程序类型更适合接入游戏盾。

游戏盾是一种专门用于游戏服务器的安全防护服务,旨在抵御各种网络攻击。它的原理主要包括以下几个方面: 流量清洗和过滤:游戏盾会对进入游戏服务器的流量进行实时监测、分析和过滤。它通过识别恶意流量和攻击流量,过滤掉其中的攻击…

SVM原理理解

目录 概念推导: 共识:距离两个点集距离最大的分类直线的泛化能力更好,更能适应复杂数据。 怎么能让margin最大? 最大化margin即: 拉格朗日乘子法: 为什么公式中出现求和符号? SVM模型: 小结&#…

css弹窗动画效果,示例弹窗从底部弹出

从底部弹出来,有过渡动画效果 用max-height可以自适应内容的高度,当内容会超过最大高度时可以在弹窗里加个scroll-view 弹窗不能用v-if来隐藏,不然transition没效果,transition只能对已有dom元素起效果,所以用透明和v…

55.MQ高级特性

目录 一、RabbitMQ部署指南。 1)单机部署。 1.1.下载镜像 1.2.安装MQ 2)安装DelayExchange插件。 2.1.下载插件 2.2.上传插件 2.3.安装插件 2.4.使用插件。 3)集群部署。 3.1.集群分类 3.2.获取cookie 3.3.准备集群配置 3.4.启…

【开源】基于JAVA语言的农家乐订餐系统

项目编号: S 043 ,文末获取源码。 \color{red}{项目编号:S043,文末获取源码。} 项目编号:S043,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户2.2 管理员 三、系统展示四、核…

Day15——File类与IO流

1.java.io.File类的使用 1.1 File类的理解 File 类及本章下的各种流,都定义在 java.io 包下。一个 File 对象代表硬盘或网络中可能存在的一个文件或者文件目录(俗称文件夹),与平台无关。(体会万事万物皆对象&#xf…

Qt 输入一组数,排序后用柱状图显示

Qt柱状图&#xff0c;需要使用到QChart模块&#xff0c;因此需要在安装Qt时勾选上QChart模块。然后在工程.pro文件中加上 QT charts 参考代码&#xff1a; //MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QPushButton…

Global IIIumination(GI)全局光照原理(一)3D空间全局光照

文章目录 一、Global IIIumination&#xff08;GI&#xff09;全局光照基本概念二、主流的全局光照方法&#xff1a;三、Reflective shadow maps&#xff08;RSM&#xff09;反射阴影贴图 全局光照四、Light Propagation Volumes (LPV)光线传播体积 全局光照1.第一步&#xff0…

Apache Flink(四):Flink 其他实时计算框架对比

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 根据前文描述我们知道Flink主要处…

Qt::UniqueConnection和lambda一块用无效

如果槽函数是lambda。 那么用了Qt::UniqueConnection也会出现槽函数被多次调用的问题。 原因&#xff1a; 参考官方文档&#xff1a; QObject Class | Qt Core 5.15.16https://doc.qt.io/qt-5/qobject.html#connect

UE Websocket笔记

参考链接 [UE4 C入门到进阶]12.Websocket网络通信 - 哔哩哔哩 包含怎么用Nodejs 写测试服务器 UE4_使用WebSocket和Json&#xff08;上&#xff09; - 知乎 包含Python写测试服务器 UE4_使用WebSocket和Json&#xff08;下&#xff09; - 知乎 示例代码 xxx.Build.cs"W…

万界星空科技MES---制造企业的加工生产模式

在现代制造业中&#xff0c;加工生产模式是制造企业组织和管理生产过程的重要方面。不同的加工模式适用于不同的生产需求和产品类型。其中流水型、离散型和混合型是三种常见的加工生产模式。1. 流水型加工模式 流水型加工模式是一种高度自动化的生产方式&#xff0c;适用于…