当前位置: 首页 > 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;暂时还没有添加动画。 视频浏览地址...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...