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

设计模式——访问者模式(Visitor Pattern)+ Spring相关源码

文章目录

  • 一、访问者模式(Visitor Pattern)
  • 二、文字描述
  • 三、例子
    • 例子一:菜鸟教程
      • 对象定义
      • 访问者定义
      • 使用
      • 总结
    • 例子二:Spring的BeanDefinitionVisitor


一、访问者模式(Visitor Pattern)

行为型模式。
目的:将数据结构数据操作分离。


二、文字描述

将对象属性的操作,交由Visitor对象进行操作。


三、例子

先说明一下。
个人认为访问者模式不一定非得按照菜鸟教程的例子来写,就像单例模式有好几种实现。
我们只需要将访问者的概念实现即可。

例子一:菜鸟教程

对象定义

public interface ComputerPart {public void accept(ComputerPartVisitor computerPartVisitor);
}
public class Monitor  implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
public class Computer implements ComputerPart {private String data;@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}

访问者定义

public interface ComputerPartVisitor {public void visit(Computer computer);public void visit(Monitor monitor);
}
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");computer.data = "修改数据";}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}

使用

ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());

总结

这个例子是菜鸟上的例子,已经被我简化了一下。
但是对于刚学这个模式的人来说,我感觉还是太绕了。


例子二:Spring的BeanDefinitionVisitor

这个Spring里面的一个类,个人认为这个比较好理解。
下面是BeanDefinitionVisitor的代码。
为了方便理解,代码比较长的方法已经被我删了,完整代码可以自己去spring看。

public class BeanDefinitionVisitor {@Nullableprivate StringValueResolver valueResolver;public BeanDefinitionVisitor(StringValueResolver valueResolver) {Assert.notNull(valueResolver, "StringValueResolver must not be null");this.valueResolver = valueResolver;}protected BeanDefinitionVisitor() {}protected void visitParentName(BeanDefinition beanDefinition) {String parentName = beanDefinition.getParentName();if (parentName != null) {String resolvedName = this.resolveStringValue(parentName);if (!parentName.equals(resolvedName)) {beanDefinition.setParentName(resolvedName);}}}protected void visitBeanClassName(BeanDefinition beanDefinition) {String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null) {String resolvedName = this.resolveStringValue(beanClassName);if (!beanClassName.equals(resolvedName)) {beanDefinition.setBeanClassName(resolvedName);}}}protected void visitFactoryBeanName(BeanDefinition beanDefinition) {String factoryBeanName = beanDefinition.getFactoryBeanName();if (factoryBeanName != null) {String resolvedName = this.resolveStringValue(factoryBeanName);if (!factoryBeanName.equals(resolvedName)) {beanDefinition.setFactoryBeanName(resolvedName);}}}protected void visitFactoryMethodName(BeanDefinition beanDefinition) {String factoryMethodName = beanDefinition.getFactoryMethodName();if (factoryMethodName != null) {String resolvedName = this.resolveStringValue(factoryMethodName);if (!factoryMethodName.equals(resolvedName)) {beanDefinition.setFactoryMethodName(resolvedName);}}}protected void visitScope(BeanDefinition beanDefinition) {String scope = beanDefinition.getScope();if (scope != null) {String resolvedScope = this.resolveStringValue(scope);if (!scope.equals(resolvedScope)) {beanDefinition.setScope(resolvedScope);}}}protected void visitPropertyValues(MutablePropertyValues pvs) {PropertyValue[] pvArray = pvs.getPropertyValues();PropertyValue[] var3 = pvArray;int var4 = pvArray.length;for(int var5 = 0; var5 < var4; ++var5) {PropertyValue pv = var3[var5];Object newVal = this.resolveValue(pv.getValue());if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {pvs.add(pv.getName(), newVal);}}}protected void visitArray(Object[] arrayVal) {for(int i = 0; i < arrayVal.length; ++i) {Object elem = arrayVal[i];Object newVal = this.resolveValue(elem);if (!ObjectUtils.nullSafeEquals(newVal, elem)) {arrayVal[i] = newVal;}}}protected void visitList(List listVal) {for(int i = 0; i < listVal.size(); ++i) {Object elem = listVal.get(i);Object newVal = this.resolveValue(elem);if (!ObjectUtils.nullSafeEquals(newVal, elem)) {listVal.set(i, newVal);}}}@Nullableprotected String resolveStringValue(String strVal) {if (this.valueResolver == null) {throw new IllegalStateException("No StringValueResolver specified - pass a resolver object into the constructor or override the 'resolveStringValue' method");} else {String resolvedValue = this.valueResolver.resolveStringValue(strVal);return strVal.equals(resolvedValue) ? strVal : resolvedValue;}}
}

这里就是用访问者的方法去设置BeanDefinition的属性,个人认为这个例子比较好理解。
简单粗暴,就是将数据结构和数据操作分离,BeanDefinition将设置属性的操作交给了BeanDefinitionVisitor 操作。

相关文章:

设计模式——访问者模式(Visitor Pattern)+ Spring相关源码

文章目录 一、访问者模式&#xff08;Visitor Pattern&#xff09;二、文字描述三、例子例子一&#xff1a;菜鸟教程对象定义访问者定义使用总结 例子二&#xff1a;Spring的BeanDefinitionVisitor 一、访问者模式&#xff08;Visitor Pattern&#xff09; 行为型模式。 目的&…...

SQL Delete 语句(删除表中的记录)

SQL DELETE 语句 DELETE语句用于删除表中现有记录。 SQL DELETE 语法 DELETE FROM table_name WHERE condition; 请注意删除表格中的记录时要小心&#xff01;注意SQL DELETE 语句中的 WHERE 子句&#xff01; WHERE子句指定需要删除哪些记录。如果省略了WHERE子句&#xff…...

在 Android 上测试 Kotlin 数据流

文章目录 一 创建虚构数据提供方二 在测试中断言数据流发出测试期间持续收集 三 测试 StateFlow使用 stateIn 创建的 StateFlow 转自&#xff1a; https://developer.android.google.cn/kotlin/flow/test?hlzh-cn#producer 与数据流进行通信的单元或模块的测试方式取决于受测对…...

day43

今日内容 python操作MySQL(重要) SQL注入问题(安全相关的xss,csrf) 视图(了解) 触发器(了解) 事务(重要) 存储过程(了解) 内置函数(了解&#xff0c;很多) 流程控制(了解) 索引(重点) python操作MySQL MySQL本身就是一款c/s架构&#xff0c;有服务端、有客户端&…...

终端管理制度

1、总则 1.1、目的 为规范XXXXX单位员工在使用计算机终端过程中的行为&#xff0c;提高计算机终端的安全性&#xff0c;确保员工安全使用计算机终端&#xff0c;特制定本制度。 1.2、范围 本规定适用于在XXXXX单位使用计算机终端的所有员工&#xff0c;包括内部终端和外部终…...

视频相关学习笔记

YUV 和rgb一样是一种表示色彩的格式&#xff0c;Y表示亮度&#xff0c;UV表示色度&#xff08;U是蓝色投影&#xff0c;V是红色投影&#xff09;&#xff0c;只有Y就是黑白的&#xff0c;所以这个格式的视频图片可以兼容黑白电视&#xff0c;所以彩色电视使用的都是YUV 存储方…...

神经网络中epoch、batch、batchsize区别

目录 1 epoch 2 batch 3 batchsize 4 区别 1 epoch 当数据集中的全部数据样本通过神经网络一次并且返回一次的过程即完成一次训练称为一个epoch。 当我们分批学习时,每次使用过全部训练数据完成一次Forword运算以及一次BP运算,称为完成了一次epoch。 epoch时期 = 所有训练…...

如何将Mysql数据库的表导出并导入到另外的架构

如何将Mysql数据库的表导出并导入到另外的架构 准备一、解决方法1.右键->导出->用mysqldump导出2.注意路径一般为&#xff1a;C:/Program Files/MySQL/MySQL Server 8.0/bin/mysqldump.exe和导出的sql文件位置3.右键->SQL脚本->运行SQL脚本4.找到SQL脚本并点击确定…...

【tio-websocket】9、服务配置与维护—TioConfig

场景 我们在写 TCP Server 时,都会先选好一个端口以监听客户端连接,再创建N组线程池来执行相关的任务,譬如发送消息、解码数据包、处理数据包等任务,还要维护客户端连接的各种数据,为了和业务互动,还要把这些客户端连接和各种业务数据绑定起来,譬如把某个客户端绑定到一…...

数据结构—线性表(下)

文章目录 6.线性表(下)(4).栈与队列的定义和ADT#1.ADT#2.栈的基本实现#3.队列的形式#4.队列的几种实现 (5).栈与队列的应用#1.栈的应用i.后缀表达式求值ii.中缀表达式转后缀表达式 #2.队列的应用 (6).线性表的其他存储方式#1.索引存储#2.哈希存储i.什么是哈希存储ii.碰撞了怎么…...

apisix之插件开发,包含java和lua两种方式

https://download.csdn.net/download/tiantangpw/88475630 有ppt和springboot程序包,可以运行...

【面试经典150 | 链表】合并两个有序链表

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;递归方法二&#xff1a;迭代 写在最后 Tag 【递归】【迭代】【链表】 题目来源 21. 合并两个有序链表 题目解读 合并两个有序链表。 解题思路 一种朴素的想法是将两个链表中的值存入到数组中&#xff0c;然后对数组…...

【linux】麒麟v10安装Redis主从集群(ARM架构)

安装redis单示例的请看&#xff1a;麒麟v10安装Redis&#xff08;ARM架构&#xff09; 安装环境 ​Hostname​IP addressmaster192.168.0.1slave1192.168.0.2slave2192.168.0.3 下载安装包 &#xff08;三台都操作&#xff09; wget https://repo.huaweicloud.com/kunpeng/…...

解决k8s删除名称空间无法强制删除的问题

问题起因&#xff1a;删除k8s名称空间的时候&#xff08;此时名称空间下还有很多pod&#xff09;一直删不掉&#xff0c;被我强行ctrl c了&#xff0c; 问题表象&#xff1a;然后就出现下面这悲催的一幕了&#xff0c;两个名称空间一直处于Terminating了 [rootmaster02 ~]# ku…...

华为---DHCP中继代理简介及示例配置

DHCP中继代理简介 IP动态获取过程中&#xff0c;客户端&#xff08;DHCP Client&#xff09;总是以广播&#xff08;广播帧及广播IP报文&#xff09;方式来发送DHCPDISCOVER和DHCPREQUEST消息的。如果服务器&#xff08;DHCP Server&#xff09;和 客户端不在同一个二层网络(二…...

五、W5100S/W5500+RP2040树莓派Pico<UDP Client数据回环测试>

文章目录 1. 前言2. 协议简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. UDP Client回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 UDP是一种无连接的网络协议&#xff0c;它提供了一种简单的、不可靠的方式来…...

死锁Deadlock

定义 死锁是指两个或多个线程互相持有对方所需的资源&#xff0c;从而导致它们无法继续执行的情况。如下图所示&#xff0c;现有两个线程&#xff0c;分别是线程A及线程B&#xff0c;线程A持有锁A&#xff0c;线程B持有锁B。此时线程A想获取锁B&#xff0c;但锁B需等到线程B的结…...

【spark客户端】Spark SQL CLI详解:怎么执行sql文件、注释怎么写,支持的文件路径协议、交互式模式使用细节

文章目录 一. Spark SQL Command Line Options(命令行参数)二. The hiverc File1. without the -i2. .hiverc 介绍 三. 支持的路径协议四. 支持的注释类型五. Spark SQL CLI交互式命令六. Examples1. running a query from the command line2. setting Hive configuration vari…...

虹科干货 | HK-TrueNAS版本大揭秘!一文教您如何选择合适的TrueNAS软件

文章来源&#xff1a;虹科网络基础设施 阅读原文&#xff1a;https://mp.weixin.qq.com/s/Iv0zDDmiDgE9vEGlAZs-sg 1&#xff0e;导语 TrueNAS是虹科iXsystems 设计和开发的NAS 操作系统&#xff0c;提供许多功能&#xff0c;例如文件存储、虚拟机 (VM) 和媒体服务器。它基于…...

前端html+css+js实现的2048小游戏,很完善。

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 逻辑用的是JavaScript&#xff0c;界面用canvas实现&#xff0c;暂时还没有添加动画。 视频浏览地址...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...