行为型:访问者模式
目录
1、核心思想
2、实现方式
2.1 模式结构
2.2 实现案例
3、优缺点分析
4、适用场景
1、核心思想
目的:数据结构稳定的情况下,解决数据与算法的耦合问题。适用于对象结构稳定但需频繁扩展操作的场景。
实现:在访问数据时根据数据类型(重载)自动切换(双重分派)到对应的算法,实现数据的自动响应机制,并且确保算法的自由扩展。
核心:对重载方法与双派发方式的利用
-
双重分派(Double Dispatch):通过两次方法调用(先接受访问者,再调用访问者的方法)实现动态绑定。
-
解耦数据与操作:对象结构中的元素(如文档节点、抽象语法树节点)仅定义“接受访问者”的方法,具体操作由访问者实现。
举例:
1> 超市对不同商品有不同的折扣力度和计价方式
2> 文档中有不同对象(文本、图片)转换成PDF或渲染到屏幕两种输出方式
2、实现方式
2.1 模式结构
五种核心角色:
- Element(元素接口):被访问的数据元素接口,定义一个可以接待访问者的行为标准accept(Visitor visitor),且所有数据封装类需实现此接口,通常作为泛型并被包含在对象容器中。
- ConcreteElement(元素实现):具体数据元素实现类,可以有多个实现,并且相对固定。其accept实现方法中调用访问者并将自己“this”传回(如
visitor.visit(this)
)。 - Visitor(访问者接口):可以是接口或者抽象类,定义了一系列访问操作方法以处理所有数据元素,通常为同名的访问方法,并以数据元素类作为入参来确定哪个重载方法被调用。
- ConcreteVisitor(访问者实现):访问者接口的实现类,可以有多个实现,每个访问者类都需实现所有数据元素类型的访问重载方法。
- ObjectContainer(对象容器):包含所有可被访问的数据对象(元素)的容器--元素的集合(如列表、树),提供遍历元素的方法,供访问者访问。
2.2 实现案例
假设有一个文档对象结构,包含文本和图片元素,需要支持导出为PDF和渲染到屏幕两种操作:
//1、元素接口
interface DocumentElement {void accept(Visitor visitor);
}//2、元素实现
// 具体元素:文本
class TextElement implements DocumentElement {private String content;public TextElement(String content) {this.content = content;}public String getContent() { return content; }@Overridepublic void accept(Visitor visitor) {visitor.visit(this); // 调用访问者的visit(TextElement)方法}
}// 具体元素:图片
class ImageElement implements DocumentElement {private String path;public ImageElement(String path) {this.path = path;}public String getPath() { return path; }@Overridepublic void accept(Visitor visitor) {visitor.visit(this); // 调用访问者的visit(ImageElement)方法}
}//3、访问者接口
interface Visitor {void visit(TextElement text);void visit(ImageElement image);
}//4、访问者实现
// 具体访问者:导出为PDF
class ExportToPDFVisitor implements Visitor {@Overridepublic void visit(TextElement text) {System.out.println("导出文本内容到PDF: " + text.getContent());}@Overridepublic void visit(ImageElement image) {System.out.println("导出图片到PDF: " + image.getPath());}
}// 具体访问者:渲染到屏幕
class RenderVisitor implements Visitor {@Overridepublic void visit(TextElement text) {System.out.println("显示文本: " + text.getContent());}@Overridepublic void visit(ImageElement image) {System.out.println("显示图片: " + image.getPath());}
}//5、对象容器:文档对象
class Document {private List<DocumentElement> elements = new ArrayList<>();public void addElement(DocumentElement element) {elements.add(element);}// 允许访问者遍历所有元素public void accept(Visitor visitor) {for (DocumentElement element : elements) {element.accept(visitor);}}
}//6、客户端
public class Client {public static void main(String[] args) {Document doc = new Document();doc.addElement(new TextElement("Hello World"));doc.addElement(new ImageElement("photo.jpg"));// 导出为PDFVisitor exportVisitor = new ExportToPDFVisitor();doc.accept(exportVisitor);// 输出:// 导出文本内容到PDF: Hello World// 导出图片到PDF: photo.jpg// 渲染到屏幕Visitor renderVisitor = new RenderVisitor();doc.accept(renderVisitor);// 输出:// 显示文本: Hello World// 显示图片: photo.jpg}
}
3、优缺点分析
优点:
-
开闭原则:新增操作(访问者)无需修改元素类。
-
集中操作逻辑:将相关操作聚合到访问者中,便于维护。
-
支持复杂操作:访问者可跨多个元素类实现全局逻辑(如统计文档字数)。
缺点:
-
破坏封装性:访问者需访问元素的内部状态,可能导致元素暴露私有字段。
-
元素类扩展困难:新增元素类需修改所有访问者接口及实现。
-
复杂度高:双重分派机制理解成本较高,代码结构更复杂。
4、适用场景
-
对象结构稳定但操作多变
-
如编译器中的抽象语法树(AST)处理(类型检查、代码生成、格式化)。
-
-
跨元素类的复杂操作
-
如统计报表生成、文档格式转换。
-
-
解耦数据与操作
-
如GUI框架中,控件树支持多种事件处理逻辑。
-
相关文章:

行为型:访问者模式
目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 1、核心思想 目的:数据结构稳定的情况下,解决数据与算法的耦合问题。适用于对象结构稳定但需频繁扩展操作的场景。 实现:在访问数据时根据数据类…...

C++数据结构 : 哈希表的实现
C数据结构 : 哈希表的实现 目录 C数据结构 : 哈希表的实现引言1. 哈希概念1.1 直接定址法1.2 哈希冲突1.3 负载因子 2. 哈希函数2.1 除法散列法/除留余数法2.2 乘法散列法(了解)2.3 全域散列法(了解) 3. 处…...
抖音电商客户端一面面经
抖音电商客户端一面面经 时间: 25.05.30 岗位: 抖音电商客户端开发工程师 形式: 技术一面 刚刚结束了字节跳动抖音电商客户端开发工程师岗位的技术一面,整体感觉考察范围非常全面,涵盖了基础、项目、算法、系统设计等…...
JavaScript 在 AcroForm 中的广泛应用
在Adobe表单(特别是SAP Interactive Forms by Adobe)中使用JavaScript的各种技巧和方法,下面这些代码片段可以帮助开发者更高效地处理表单逻辑和交互。 1. 获取数据内容 从上下文结构中获取数据 var LV_DATA = xfa.resolveNode("$record.IM_TEST.FIELDNAME").val…...
Socket编程之TCP套件字
基于的TCP套件字编程流程 1. Socket套接字 Socket是一个编程接口(网络编程接口),是一种特殊的文件描述符(write/read)。Socket并不 仅限于TCP/IP Socket独立于具体协议的编程接口,这个接口位于TCP/IP四层…...

AD9268、AD9643调试过程中遇到的问题
Ad9268芯片 AD9268是一款双通道、16位、80 MSPS/105 MSPS/125 MSPS模数转换器(ADC)。AD9268旨在支持要求高性能、低成本、小尺寸和多功能的通信应用。双通道ADC内核采用多级差分流水线架构,集成输出纠错逻辑。每个ADC都具有宽带宽、差分采样保持模拟输入放大器&…...
Java-File类基本方法使用指南
Java-File类基本方法使用指南 一、File类基础概念1.1 什么是File类1.2 File类的构造函数 二、文件和目录的创建与删除2.1 创建文件 - createNewFile()2.2 创建目录 - mkdir() 和 mkdirs()2.3 删除文件或目录 - delete() 三、文件和目录的查询与判断3.1 存在性判断 - exists()3.…...
Python爬虫实战:研究PyQuery库相关技术
1. 引言 1.1 研究背景与意义 随着互联网的快速发展,网络上的数据量呈爆炸式增长。如何高效地从海量的网页数据中提取有价值的信息,成为当前信息技术领域的一个重要研究方向。网络爬虫作为一种自动获取网页内容的程序,能够按照一定的规则,自动地抓取万维网信息,在搜索引擎…...
第九篇:MySQL 安全加固与访问控制策略实战
数据库的安全不仅仅是防止外部入侵,更包括合理配置账户权限、日志审计、网络加密、配置加固等。本文将系统性梳理 MySQL 的安全机制与实战加固方法,助你构建安全可靠的数据库运行环境。 一、数据库安全风险面 数据库常面临的威胁: 弱口令或默…...
神经网络-Day40
目录 单通道图片的规范写法图像任务中的张量形状NLP任务中的张量形状1. **Flatten操作**2. **view/reshape操作** 总结彩色图片的规范写法 图像数据的格式以及模型定义的过程,和之前结构化数据的略有不同,主要差异体现在2处 模型定义的时候需要展平图像由…...
WindowServer2022下docker方式安装dify步骤
WindowServer2022下docker方式安装dify步骤(稳定后考虑部署至linux中) 教程:https://blog.csdn.net/qq_49035156/article/details/143264534 0、资源要求 ---windows:8核CPU、16G内存、200G500G存储 ---10.21.31.122/administra…...
Java五种方法批量处理List元素全解
Java:如何优雅批量处理List中的每个元素 一、场景分析:为什么需要批量处理List?二、核心方法:五种实现方式对比2.1 普通for循环(最直接的方式)代码示例:优缺点: 2.2 Java 8 replaceAllÿ…...
springboot文件上传下载
基于ResponseEntity的下载响应 SpringBoot中,ResponseEntity类型可以精确控制HTTP响应,为文件下载提供完善的HTTP头信息。 RestController RequestMapping("/api/download") public class FileDownloadController {GetMapping("/file/{…...

webpack CDN打包优化
CDN网络分发服务 请求资源时最近的服务器将缓存内容交给用户 体积较大且变动不多的文件存在CDN文件中 react react-dom资源 // 添加自定义对于webpack的配置const path require(path) const { whenProd, getPlugin, pluginByName } require(craco/craco)module.exports {//…...

ARM内核一览
经常看介绍某某牛批芯片用的又是ARM什么核,看的云里雾里,所以简单整理整理。(内容来自官网和GPT) 1 ARM 内核总体分类 系列特点应用场景Cortex-M超低功耗、低成本、实时性嵌入式系统、微控制器、IoTCortex-R高可靠性、硬实时汽车…...

Rust 和 Python 如何混合使用
Rust 与 Python 可以通过多种方式混合使用,如 FFI 接口、PyO3 库、CFFI、CPython API、wasm 模块嵌入等。这种混合开发模式可结合 Rust 的性能优势与 Python 的开发效率。其中,PyO3 是目前最受欢迎的桥接工具,它允许使用 Rust 编写 Python 扩…...

台式电脑CPU天梯图_2025年台式电脑CPU天梯图
CPU的选择绝对是重中之重,它关乎了一台电脑性能好坏。相信不少用户,在挑选CPU的时候不知道谁强谁弱,尤其是intel和AMD两款CPU之间。下面通过2025年台式电脑CPU天梯图来了解下这两款cpu. 2025年台式电脑CPU天梯图 2025年台式电脑CPU天梯图包含了老旧型号以及12代、13代、14代…...

2025年渗透测试面试题总结-匿名[校招]安全服务工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 匿名[校招]安全服务工程师 一面问题与完整回答 1. 学校、专业、成绩与排名 2. 学习安全时长 3. 当前学习…...

Deseq2:MAG相对丰度差异检验
首先使用代码将contigs和MAG联系起来 https://github.com/MrOlm/drep/blob/master/helper_scripts/parse_stb.py ~/parse_stb.py --reverse -f ~/bin_dir/* -o ~/bin_dir/genomes.stb # 查看第一列的contigs有没有重复(重复的话会影响后续比对) awk {p…...

CTFHub-RCE 命令注入-过滤目录分隔符
观察源代码 代码里面可以发现过滤了目录分隔符\和/ 判断是Windows还是Linux 源代码中有 ping -c 4 说明是Linux 查看有哪些文件 127.0.0.1|ls 打开flag文件 发现存在一个flag_is_here的文件夹,我们需要打开这个文件夹找到目标文件我们尝试分步,先利…...
从零开始的数据结构教程(七) 回溯算法
🔄 标题一:回溯核心思想——走迷宫时的“穷举回头”策略 回溯算法 (Backtracking) 是一种通过探索所有可能的候选解来找出所有的解或某些解的算法。它就像你在一个复杂的迷宫中寻找出路:当你遇到一个岔路口时,你会选择一条路继续…...

CentOS-stream-9 Zabbix的安装与配置
一、Web环境搭建部署Zabbix时,选择合适的MariaDB、PHP和Nginx版本非常重要,以确保兼容性和最佳性能。以下是建议版本:Zabbix 6.4 MariaDB:官方文档推荐使用MariaDB 10.3或更高版本。对于CentOS Stream 9,建议使用Maria…...

开源是什么?我们为什么要开源?
本片为故事类文章推荐听音频哦 软件自由运动的背景 梦开始的地方 20世纪70年代,软件行业处于早期发展阶段,软件通常与硬件捆绑销售,用户对软件的使用、修改和分发权利非常有限。随着计算机技术的发展和互联网的普及,越来越多的开…...

【unity游戏开发——编辑器扩展】EditorApplication公共类处理编辑器生命周期事件、播放模式控制以及各种编辑器状态查询
注意:考虑到编辑器扩展的内容比较多,我将编辑器扩展的内容分开,并全部整合放在【unity游戏开发——编辑器扩展】专栏里,感兴趣的小伙伴可以前往逐一查看学习。 文章目录 前言一、监听编辑器事件1、常用编辑器事件2、示例监听播放模…...
elasticsearch低频字段优化
在Elasticsearch中,通过设置"index": false关闭低频字段的倒排索引构建是常见的优化手段,以下是关键要点: 一、核心机制 倒排索引禁用 设置index: false后,字段不会生成倒排索引,无法通过常规查…...

React---day3
React 2.5 jsx的本质 jsx 仅仅只是 React.createElement(component, props, …children) 函数的语法糖。所有的jsx最终都会被转换成React.createElement的函数调用。 createElement需要传递三个参数: 参数一:type 当前ReactElement的类型;…...

PyCharm接入DeepSeek,实现高效AI编程
介绍本土AI工具DeepSeek如何结合PyCharm同样实现该功能。 一 DeepSeek API申请 首先进入DeepSeek官网:DeepSeek 官网 接着点击右上角的 “API 开放平台“ 然后点击API keys 创建好的API key,记得复制保存好 二 pycharm 接入deepseek 首先打开PyCh…...
前端面经 get和post区别
get获取数据 post提交资源,引起服务器状态变化或者副作用 区别 1get会比post更不安全 get参数写在url中 post在请求体内 2get报文 head和body一起发 响应200 post报文 先发head 100 再发 body 200 3 get请求url有长度限制 4 默认缓存get 请求...

CTFSHOW-WEB-36D杯
给你shell 这道题对我这个新手还是有难度的,花了不少时间。首先f12看源码,看到?view_source,点进去看源码 <?php //Its no need to use scanner. Of course if you want, but u will find nothing. error_reporting(0); include "…...
MySQL connection close 后, mysql server上的行为是什么
本文着重讲述的是通过 msql client 连接到 mysql server ,发起 update 、 select 操作(由于数据量非常大,所以 update、select 操作都很耗时,即在结果返回前我们有足够的时间执行一些操作) 。 在客户端分别尝试执行 ctrl C 结束关闭 mysql c…...