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

设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码

文章目录

  • 一、装饰器模式的定义
  • 二、个人理解
    • 举个抽象的例(可能并不是很贴切)
  • 三、例子
    • 1、菜鸟教程例子
      • 1.1、定义对象
      • 1.2、定义装饰器
    • 3、JDK源码 ——包装类
    • 4、JDK源码 —— IO、OutputStreamWriter
    • 5、Spring源码 —— BeanWrapperImpl
    • 5、SpringMVC源码 —— HttpHeadResponseDecorator
  • 四、其他设计模式

一、装饰器模式的定义

  • 别名:包装模式(Wrapper Pattern)
  • 类型:结构型模式。
  • 目的:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责额外功能。

二、个人理解

给对象添加新功能时,并不是在对象类中直接添加,而是在装饰器类中添加。
在装饰类中添加新功能,你可以增强原先对象的方法,也可以给对象新增一个方法。

举个抽象的例(可能并不是很贴切)

假设要给人类添加开炮功能。
但由于这是人类,咱们不能通过继承直接给人类添加开炮功能
所以我们就得通过组合,将机器和人类组合起来、通过变相实现人类可以开炮。
这个机器就是装饰器。

  • 坦克 + 人类 ,实现开炮功能
  • 高达 + 人类 ,实现开炮功能

三、例子

1、菜鸟教程例子

菜鸟教程的例子都将对象和装饰器进行了抽象处理,实现了可替换对象和装饰器的实现类。
菜鸟教程原例子
个人觉得这样理解装饰器太绕了,下面的例子就只保留了对象和装饰器

1.1、定义对象

定义一个圆的对象

public class Circle{@Overridepublic void draw() {System.out.println("Shape: Circle");}
}

1.2、定义装饰器

新增setRedBorder方法去设置红色边框。

public class RedCircleDecorator{private Circle c;public RedCircleDecorator(Circle c) {this.c = c;}@Overridepublic void draw() {decoratedShape.draw();         setRedBorder(decoratedShape);}private void setRedBorder(Circle decoratedShape){System.out.println("Border Color: Red");}
}

但我觉这个菜鸟这个例子并不能把装饰器模式特点表现出来
因setRedBorder是私有,并且只是把原先draw方法进行了增强。
这样的话,代理模式也能实现,代理模式也能增强原有的方法,所以这里并不能把装饰器模式特点表现出来
所以我改了一下。

public class ColorCircleDecorator{private Circle c;public RedCircleDecorator(Circle c) {this.c = c;}@Overridepublic void draw() {decoratedShape.draw();System.out.println("画了个普通的圆");         }public void drawRedCircle(Circle decoratedShape){decoratedShape.draw();System.out.println("画了个红色的圆");}public void drawBlueCircle(Circle decoratedShape){decoratedShape.draw();System.out.println("画了个蓝色的圆");}
}

这个例子保留了原先的draw功能,又新增了drawRedCircle和drawBlueCircle功能。

3、JDK源码 ——包装类

包装类也运用了装饰器模式。
将基本类型 转 包装类 的同时,还提供各种转换类型的功能。

4、JDK源码 —— IO、OutputStreamWriter

OutputStreamWriter同时运用了装饰器模式+适配器模式。
这里我们拿装饰器部分来讲。

FileOutputStream fos = new FileOutputStream(new File("Y:/学习资料.md"));
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.append("新资料xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

原本FileOutputStream 是原本没有append功能的,
而在中OutputStreamWriter 添加append功能。
源码:

public class OutputStreamWriter extends Writer {private final StreamEncoder se;public OutputStreamWriter(OutputStream out) {super(out);se = StreamEncoder.forOutputStreamWriter(out, lockFor(this),out instanceof PrintStream ps ? ps.charset() : Charset.defaultCharset());}@Overridepublic Writer append(CharSequence csq) throws IOException {if (csq instanceof CharBuffer) {se.write((CharBuffer) csq);} else {se.write(String.valueOf(csq));}return this;}
}

可以看到虽然OutputStreamWriter 重写了append方法。
但构造器里OutputStream又被新的装饰器StreamEncoder接收。
而StreamEncoder类就已经通过继承Writer 增加了append方法。

public final class StreamEncoder extends Writer {private final OutputStream out;private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {super(lock);this.out = out;this.ch = null;this.cs = enc.charset();this.encoder = enc;this.bb = ByteBuffer.allocate(INITIAL_BYTE_BUFFER_CAPACITY);this.maxBufferCapacity = MAX_BYTE_BUFFER_CAPACITY;}public static StreamEncoder forOutputStreamWriter(OutputStream out, Object lock, Charset cs) {return new StreamEncoder(out, lock, cs);}
}

5、Spring源码 —— BeanWrapperImpl

BeanWrapperImpl类是对BeanWrapper接口的默认实现,它包装了一个bean对象,缓存了bean的内省结果,并可以访问bean的属性、设置bean的属性值。

BeanWrapperImpl功能还挺复杂的,大家可以自行去看源码,我就不贴出来了。

5、SpringMVC源码 —— HttpHeadResponseDecorator

HttpHeadResponseDecorator 给ServerHttpResponse 添加了writeWith、writeAndFlushWith的功能。

public class HttpHeadResponseDecorator extends ServerHttpResponseDecorator {public HttpHeadResponseDecorator(ServerHttpResponse delegate) {super(delegate);}public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {return this.shouldSetContentLength() && body instanceof Mono ? ((Mono)body).doOnSuccess((buffer) -> {if (buffer != null) {this.getHeaders().setContentLength((long)buffer.readableByteCount());DataBufferUtils.release(buffer);} else {this.getHeaders().setContentLength(0L);}}).then() : Flux.from(body).doOnNext(DataBufferUtils::release).then();}private boolean shouldSetContentLength() {return this.getHeaders().getFirst("Content-Length") == null && this.getHeaders().getFirst("Transfer-Encoding") == null;}public final Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {return this.setComplete();}
}

四、其他设计模式

创建型模式
结构型模式

  • 1、设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码

行为型模式

  • 1、设计模式——访问者模式(Visitor Pattern)+ Spring相关源码
  • 2、设计模式——中介者模式(Mediator Pattern)+ JDK相关源码

相关文章:

设计模式——装饰器模式(Decorator Pattern)+ Spring相关源码

文章目录 一、装饰器模式的定义二、个人理解举个抽象的例&#xff08;可能并不是很贴切&#xff09; 三、例子1、菜鸟教程例子1.1、定义对象1.2、定义装饰器 3、JDK源码 ——包装类4、JDK源码 —— IO、OutputStreamWriter5、Spring源码 —— BeanWrapperImpl5、SpringMVC源码 …...

MATLAB R2018b详细安装教程(附资源)

云盘链接&#xff1a; pan.baidu.com/s/1SsfNtlG96umfXdhaEOPT1g 提取码&#xff1a;1024 大小&#xff1a;11.77GB 安装环境&#xff1a;Win10/Win8/Win7 安装步骤&#xff1a; 1.鼠标右击【R2018b(64bit)】压缩包选择【解压到 R2018b(64bit)】 2.打开解压后的文件夹中的…...

GEE错误——影像加载过程中出现的图层无法展示的解决方案

问题&#xff1a; // I dont know if some standard value exists for the radius, in the same, I will assume that some software would prefer to use square shape, but circle makes more sense to me. // pixels is noice if you want to zoom in and out to visualize…...

读图数据库实战笔记03_遍历

1. Gremlin Server只将数据存储在内存中 1.1. 如果停止Gremlin Server&#xff0c;将丢失数据库里的所有数据 2. 概念 2.1. 遍历&#xff08;动词&#xff09; 2.1.1. 当在图数据库中导航时&#xff0c;从顶点到边或从边到顶点的移动过程 2.1.2. 类似于在关系数据库中的查…...

QT如何检测当前系统是是Windows还是Uninx或Mac?以及是哪个版本?

简介 通过Qt获取当前系统及版本号&#xff0c;需要用到QSysInfo。 QSysInfo类提供有关系统的信息。 WordSize指定了应用程序编译所在的平台的指针大小。 ByteOrder指定了平台是大端序还是小端序。 某些常量仅在特定的平台上定义。您可以使用预处理器符号Q_OS_WIN和Q_OS_MACOS来…...

Maven配置阿里云中央仓库settings.xml

Maven配置阿里云settings.xml 前言一、阿里云settings.xml二、使用步骤1.任意目录创建settings.xml2.使用阿里云仓库 总结 前言 国内网络从maven中央仓库下载文件通常是比较慢的&#xff0c;所以建议配置阿里云代理镜像以提高jar包下载速度&#xff0c;IDEA中我们需要配置自己…...

由浅入深C系列八:如何高效使用和处理Json格式的数据

如何高效使用和处理JSON格式的数据 问题引入关于CJSON示例代码头文件引用处理数据 问题引入 最近的项目在用c处理后台的数据时&#xff0c;因为好多外部接口都在使用Json格式作为返回的数据结构和数据描述&#xff0c;如何在c中高效使用和处理Json格式的数据就成为了必须要解决…...

多媒体应用设计师 第16章 多媒体应用系统的设计和实现示例

口诀 思维导图 2020...

golang平滑重启库overseer实现原理

overseer主要完成了三部分功能&#xff1a; 1、连接的无损关闭&#xff0c;2、连接的平滑重启&#xff0c;3、文件变更的自动重启。 下面依次讲一下&#xff1a; 一、连接的无损关闭 golang官方的net包是不支持连接的无损关闭的&#xff0c;当主监听协程退出时&#xff0c;…...

用Python定义一个函数,用递归的方式模拟汉诺塔问题

【任务需求】 定义一个函数&#xff0c;用递归的方式模拟汉诺塔问题&#xff0c;三个柱子&#xff0c;分别为A、B、C&#xff0c;其中A柱子上有N个盘子&#xff0c;从小到大编号为1到N&#xff0c;盘子大小不同。现在要将这N个盘子从A柱子移动到C柱子上&#xff0c;但移动的过…...

二手的需求

案例1030 某天项目经理小王&#xff0c;从用户现场带回了需求&#xff0c;以图形的方式&#xff0c;交给了产品经理。告诉他就照这样设计&#xff0c;结果是项目经理放弃让产品经理出效果图。 原因是产品经理觉得项目经理带回来的需求有问题。项目经理解释产品经理不接受&…...

大厂面试题-JVM为什么使用元空间替换了永久代?

目录 面试解析 问题答案 面试解析 我们都知道Java8以及以后的版本中&#xff0c;JVM运行时数据区的结构都在慢慢调整和优化。但实际上这些变化&#xff0c;对于业务开发的小伙伴来说&#xff0c;没有任何影响。 因此我可以说&#xff0c;99%的人都回答不出这个问题。 但是…...

基本微信小程序的驾校宝典系统-驾照考试系统

项目介绍 系统模块分析是对系统的各个模块做出相应的说明以及解释。此系统的模块分别有用户模块、服务端模块和管理端模块这两大基本模块&#xff0c;其中服务端模块包括了首页、教练信息、教练咨讯、考试预约、我的等&#xff1b;而管理端模块则包括了个人中心、用户管理、教…...

02、SpringCloud -- Redis和Cookie过期时间刷新功能

目录 需求:代码流程过滤器类工具类过滤判断远程调用feign接口gitee 配置接口实现过滤器run方法测试:问题:秒杀功能完整分析图 需求: cookie应该写在网关中,网关中可以自定义filter过滤器,用来实现cookie的刷新和redis中key的刷新,延长用户的操作时间。 就是让用户每操…...

【报错】kali安装ngrok报错解决办法(zsh: exec format error: ./ngrok)

问题描述 kali安装ngrok令牌授权失败 在安装配置文件的时候报错&#xff1a;zsh: exec format error: ./ngrok 原因分析&#xff1a; 在Kali Linux上执行./ngrok时出现zsh exec格式错误的问题可能是由于未安装正确版本的ngrok或操作系统不兼容ngrok导致的。以下是一些可能的解…...

<学习笔记>从零开始自学Python-之-常用库篇(十三)内置小型数据库shelve

一、shelve简介&#xff1a; shelve是Python当中数据储存的方案&#xff0c;类似key-value数据库&#xff0c;便于保存Python对象&#xff0c;shelve只有一个open&#xff08;&#xff09;函数&#xff0c;用来打开指定的文件&#xff08;字典&#xff09;&#xff0c;会返回一…...

Redis快速上手篇七(集群-六台虚拟机)

Redis集群 主从复制的场景无法吗满足主机单点故障时需要引入集群配置 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服务器主要用来处理写请求&#xff0c;部署多台从服务器 &#…...

LeetCode 301. 删除无效的括号【字符串,回溯或BFS】困难

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

面试经典159题——Day25

文章目录 一、题目二、题解 一、题目 125. Valid Palindrome A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric charact…...

C# OpenCvSharp DNN 部署L2CS-Net人脸朝向估计

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_DNN_Demo …...

Windows环境下MosQuitto服务器搭建,安装mqtt服务端软件

1、下载、安装MosQuitto服务器 下载地址&#xff1a;http://mosquitto.org/files/binary/ 根据平台选择相应的代码下载。 安装完成后&#xff0c;安装文件夹下部分文件的功能...

web前端JS基础-----制作进度条

1&#xff0c;参考代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><progress id"pro" max"100" value"0"></progress><scrip…...

Linux命令解压多个tar.gz包

命令行解压单个tar.gz包&#xff1a; tar zxvf package.tar.gz 命令行解压多个tar.gz包&#xff1a; for f in *.tar.gz; do tar zxvf "$f"; done 这个命令会循环遍历当前目录下的所有tar.gz包&#xff0c;然后逐个解压。 注&#xff1a;如果想要解压到指定的目…...

Java基于SpringBoot+Vue的网上图书商城管理系统(附源码,教程)

文章目录 1. 简介2 技术栈3 系统功能4系统设计4.1数据库设计 5系统详细设计5.1系统功能模块5.1系统功能模块5.2管理员功能模块 源码下载地址 1. 简介 本次设计任务是要设计一个网上图书商城&#xff0c;通过这个系统能够满足网上图书商城的管理功能。系统的主要功能包括首页、…...

Visual Studio Code的下载与安装

Visual Studio Code&#xff08;简称 VS Code&#xff09;是由 Microsoft 开发的免费、开源的文本编辑器&#xff0c;适用于多种操作系统&#xff0c;包括 Windows、macOS 和 Linux。它的设计目标是成为一款轻量级、高效的代码编辑工具&#xff0c;同时提供丰富的扩展和功能&am…...

23种设计模式在SpringCloud源码里的应用

单例模式&#xff08;Singleton&#xff09;&#xff1a;Spring 中的 Bean 默认都是单例模式&#xff0c;保证在整个应用中只有一个实例。 工厂方法模式&#xff08;Factory Method&#xff09;&#xff1a;Spring 中的 BeanFactory 和 ApplicationContext 都实现了工厂方法模…...

几个精致的Linux命令

说到Linux命令&#xff0c;一些基础的简单的单个命令我就不说了&#xff0c;咱今天来点复杂的组合命令&#xff0c;比较长&#xff0c;但觉对很酷&#xff1a; 打印业务服务异常日志&#xff1a; tail -f business-service.log | grep -i exception --color 或者 grep --…...

CoDeSys系列-3、Windows运行时软PLC主站和p-net从站IO设备组网测试

CoDeSys系列-3、Windows运行时软PLC主站和p-net从站IO设备组网测试 文章目录 CoDeSys系列-3、Windows运行时软PLC主站和p-net从站IO设备组网测试一、前言二、Windows运行时软plc配置编程1、安装Windows下的运行时扩展包&#xff08;非必要&#xff09;2、创建项目2.1、创建标准…...

vscode下ssh免密登录linux服务器

vscode使用ssh免密登录linux 1、安装SSH插件2、生成密钥3、linux安装ssh服务4、linux下配置公钥5、vscode远程登录 注&#xff1a;测试环境为window10Ubuntu1804/Ubuntu2204 1、安装SSH插件 扩展->搜索SSH->点击install进行安装&#xff0c;如下图所示&#xff1a; 2、…...

基于jquery+html开发的json格式校验工具

json简介 JSON是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式&#xff0c;但是也使用了类似于C语言家族…...