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

KT0803K FM发射芯片Arduino驱动开发与射频工程实践

1. KT0803系列FM发射芯片Arduino库深度解析与工程实践指南1.1 芯片定位与系统级约束KT0803及其衍生型号&#xff08;KT0803K/L/M&#xff09;是高度集成的单芯片FM广播发射器&#xff0c;专为低功耗、小体积音频广播应用设计。该系列芯片内部集成了PLL频率合成器、立体声编码器…...

使用Image - To - image条件生成对抗网络评估乳腺癌新辅助化疗反应的动态对比增强MRI血管渗透性映射

论文总结1、提出了一种基于条件生成对抗网络&#xff08;cGAN&#xff09;的新方法&#xff0c;用于将动态对比增强磁共振成像&#xff08;DCE MRI&#xff09;快速转换为药代动力学&#xff08;PK&#xff09;血管通透性参数图&#xff08;Ktrans&#xff09;&#xff0c;以早…...

别再死记硬背Modbus了!用Python+Modbus-TCP/RTU模拟器5分钟搞懂数据帧

用PythonModbus模拟器5分钟实战协议帧解析 当你第一次接触工业通信协议时&#xff0c;那些晦涩的术语和抽象的数据帧结构是否让你望而生畏&#xff1f;作为在工业自动化领域工作多年的开发者&#xff0c;我完全理解这种挫败感。传统学习Modbus的方式往往从理论入手&#xff0c;…...

2025届毕业生推荐的五大AI论文方案推荐榜单

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 普及时&#xff0c;人工智能生成的内容让文本展现出一种高度模式化的特性&#xff0c;这一情…...

4款降AI率工具实测横评:最便宜和最贵的效果差多少?

花了几百块&#xff0c;测了一圈&#xff0c;现在把结果告诉你。 降AI率工具、降AI工具保姆级测评2026、降AI这个需求&#xff0c;不同工具之间差距其实挺明显的&#xff0c;不是"随便用一个都一样"。 我的结论&#xff1a;嘎嘎降AI&#xff08;www.aigcleaner.com…...

Cursor Pro完整解锁方案:一站式解决AI编程助手使用限制的终极指南

Cursor Pro完整解锁方案&#xff1a;一站式解决AI编程助手使用限制的终极指南 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reach…...

别再只玩单机了!用AirSim+Python实现你的第一个无人机编队(附完整代码)

从单机到编队&#xff1a;用AirSim和Python打造你的第一支无人机小队 想象一下&#xff0c;当你第一次在AirSim中成功让无人机起飞时的兴奋感——现在&#xff0c;是时候将这份快乐乘以N倍了。本文将带你跨越单机操作的舒适区&#xff0c;进入无人机编队控制的新世界。不需要复…...

通信确定性可视化冗余现场总线技术开发白皮书(能源化工交通高可靠行业 Profibus DP CAN PROFINET EtherNet/IP SPE APL)

1.前言现场总线是工业物联网的核心支撑技术&#xff0c;但当前国际主流方案在国内应用中普遍存在开发门槛高、硬件成本高、调试维护复杂、冗余配置昂贵等问题&#xff0c;难以满足中小型自动化项目及国产控制系统对高性价比、高可靠性通信的需求。CANWeb现场总线深度融合CAN的高…...

ESLint-Plugin-Unicorn规则优先级设置终极指南:如何平衡代码质量和开发效率

ESLint-Plugin-Unicorn规则优先级设置终极指南&#xff1a;如何平衡代码质量和开发效率 【免费下载链接】eslint-plugin-unicorn More than 100 powerful ESLint rules 项目地址: https://gitcode.com/gh_mirrors/es/eslint-plugin-unicorn ESLint-Plugin-Unicorn是一个…...

运维自动化新思路:使用Pixel Script Temple生成系统监控拓扑像素图

运维自动化新思路&#xff1a;使用Pixel Script Temple生成系统监控拓扑像素图 1. 引言&#xff1a;运维可视化的痛点与创新方案 每天早晨&#xff0c;运维工程师小李都要花1-2小时手动整理服务器状态报告。他需要从多个监控系统导出数据&#xff0c;在PPT中绘制网络拓扑图&a…...