设计模式:访问者模式
访问者模式(Visitor Pattern)是行为设计模式的一种,它使你能够在不修改对象结构的情况下,给对象结构中的每个元素添加新的功能。访问者模式将数据结构和作用于结构上的操作解耦,使得操作集合可相对自由地演化。
核心概念
-
Element(元素接口/抽象类):定义一个接受访问者访问的接口或抽象类,元素可以是抽象类也可以是接口,通常会有一个accept()方法用于接收访问者对象的访问。
-
ConcreteElement(具体元素类):实现了Element接口或继承了Element抽象类的具体类,每个具体元素都实现了accept()方法,用于调用访问者相应的方法。
-
Visitor(访问者接口):声明了一个或多个访问元素的方法,使得每个元素都能接受访问者的操作。这些方法的名称通常反映了访问者对元素的操作。
-
ConcreteVisitor(具体访问者类):实现了Visitor接口,为每一种ConcreteElement提供具体的操作实现。
应用场景
- 当需要对一个对象结构中的对象施加多种不同的操作,而这些操作彼此独立,且需要避免让这些操作"污染"这些对象的类时。
- 对象结构比较稳定,但经常需要在此结构上定义新的操作。
优缺点
优点:
- 扩展性好:可以在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
- 符合单一职责原则:将数据结构和数据操作分离,使得两者可以独立变化。
缺点:
- 访问者模式使得对象结构变得复杂,增加新的元素类或访问者类都需要修改原有代码,违反了开闭原则。
- 过多的ConcreteVisitor可能会导致类膨胀,系统难于维护。
以下是使用Java实现访问者模式的一个完整示例。在这个例子中,我们假设有一个简单的文件系统结构,由文件(File)和目录(Directory)组成。我们的目标是实现两种不同的访问者:一个用于计算文件系统的总大小,另一个用于打印文件系统的内容结构。
1. 定义元素接口(Element)
首先,定义一个表示文件系统元素的接口,它包含一个接受访问者的方法。
// 文件系统元素接口
interface FileSystemElement {void accept(FileSystemVisitor visitor);
}
2. 具体元素类(ConcreteElement)
然后,定义具体的文件和目录类,它们都实现了FileSystemElement
接口。
// 文件类
class File implements FileSystemElement {private String name;private int size;public File(String name, int size) {this.name = name;this.size = size;}public String getName() {return name;}public int getSize() {return size;}@Overridepublic void accept(FileSystemVisitor visitor) {visitor.visit(this);}
}// 目录类
class Directory implements FileSystemElement {private String name;private List<FileSystemElement> elements = new ArrayList<>();public Directory(String name) {this.name = name;}public void add(FileSystemElement element) {elements.add(element);}public String getName() {return name;}@Overridepublic void accept(FileSystemVisitor visitor) {visitor.visit(this);}public List<FileSystemElement> getElements() {return elements;}
}
3. 访问者接口(Visitor)
定义访问者接口,包含访问文件和目录的方法。
// 访问者接口
interface FileSystemVisitor {void visit(File file);void visit(Directory directory);
}
4. 具体访问者类(ConcreteVisitor)
创建两个访问者类,一个用于计算总大小,一个用于打印结构。
// 计算大小的访问者
class SizeCalculatorVisitor implements FileSystemVisitor {private int totalSize = 0;@Overridepublic void visit(File file) {totalSize += file.getSize();}@Overridepublic void visit(Directory directory) {for (FileSystemElement element : directory.getElements()) {element.accept(this);}}public int getTotalSize() {return totalSize;}
}// 打印结构的访问者
class StructurePrinterVisitor implements FileSystemVisitor {private String prefix = "";@Overridepublic void visit(File file) {System.out.println(prefix + "- " + file.getName() + " (" + file.getSize() + " KB)");}@Overridepublic void visit(Directory directory) {System.out.println(prefix + "+ " + directory.getName());prefix += " ";for (FileSystemElement element : directory.getElements()) {element.accept(this);}prefix = prefix.substring(2);}
}
5. 客户端代码
最后,客户端代码创建文件系统结构并使用访问者。
public class VisitorPatternDemo {public static void main(String[] args) {Directory rootDir = new Directory("root");Directory subDir = new Directory("subdir");File file1 = new File("file1.txt", 100);File file2 = new File("file2.txt", 200);rootDir.add(file1);rootDir.add(subDir);subDir.add(file2);// 使用大小计算器访问者FileSystemVisitor sizeCalculator = new SizeCalculatorVisitor();rootDir.accept(sizeCalculator);System.out.println("Total size: " + sizeCalculator.getTotalSize() + " KB");// 使用结构打印访问者System.out.println("\nPrinting structure:");FileSystemVisitor structurePrinter = new StructurePrinterVisitor();rootDir.accept(structurePrinter);}
}
这个例子展示了如何使用访问者模式来添加新的操作(计算大小和打印结构),而不需要修改文件和目录的类。新增操作时,只需添加新的访问者类即可。
相关文章:
设计模式:访问者模式
访问者模式(Visitor Pattern)是行为设计模式的一种,它使你能够在不修改对象结构的情况下,给对象结构中的每个元素添加新的功能。访问者模式将数据结构和作用于结构上的操作解耦,使得操作集合可相对自由地演化。 核心概…...

vivado Virtex-7 配置存储器器件
Virtex-7 配置存储器器件 下表所示闪存器件支持通过 Vivado 软件对 Virtex -7 器件执行擦除、空白检查、编程和验证等配置操作。 本附录中的表格所列赛灵思系列非易失性存储器将不断保持更新 , 并支持通过 Vivado 软件对其中所列非易失性存储器 进行擦除、…...

检测服务器环境,实现快速部署。适用于CRMEB_PRO/多店
运行效果如图: 最近被好多人问,本来运行的好好的,突然swoole就启动不了了。 本工具为爱发电,如果工具正好解决了您的需求。我会很开心 代码如下: """本脚本为爱发电by:网前雨刮器 """…...

Spring Security初探
url说明方法/login/oauth/authorize授权断点。无登录态时跳转到/authentication/require,有登录态时跳转到/loginorg.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint#authorize/authentication/require自己写的用于重定向到登录页面的ur…...
【Java代码审计】敏感信息泄漏篇
【Java代码审计】敏感信息泄漏篇 敏感信息泄露概述 敏感信息泄露概述 敏感信息是业务系统中对保密性要求较高的数据,通常包括系统敏感信息以及应用敏感信息 系统敏感信息指的是业务系统本身的基础环境信息,例如系统信息、中间件版本、代码信息ÿ…...

Windows Server 2012 R2 新增D盘分区
我们经常搭建windows版本的游戏时会要在D盘上操作,今天就介绍下新的服务器如何新增一个D盘。 在"开始"图标右边有个”服务器管理器“,单击点开 点开服务器管理器后,点击“工具”打开“计算机管理” 打开计算机管理后点击“存储”-…...

transformer与beter
transformer与beter 解码和编码器含义tokizer标记器和one-hot独热编码编码解码--语义较好的维度空间矩阵相乘--空间变换编码理解如何构造降维的嵌入矩阵--实现到达潜空间上面是基础,下面是transformer正文自注意力机制注意力分数--上下文修正系数为什么需要KQ两个矩…...
MySQL索引设计遵循一系列原则
高频查询与大数据量表:对查询频次较高且数据量较大的表建立索引。这是因为索引主要是为了加速查询过程,对于经常需要访问的表和数据,索引的效果最为显著。 选择合适索引字段:从WHERE子句中提取最佳候选列作为索引字段,…...

windows窗口消息队列与消息过程处理函数
在Windows窗口应用程序中,消息队列和窗口过程函数是实现消息驱动机制的核心组件。 消息队列(Message Queue): 消息队列是用于存储窗口消息的缓冲区。当用户与应用程序交互时,系统会将生成的消息插入到消息队列中&…...
【Chisel】chisel中怎么处理类似verilog的可变位宽和parameter
在 Chisel 中处理可变位宽和参数的方式与 Verilog 有一些不同,因为 Chisel 是建立在 Scala 语言之上的。以下是如何在 Chisel 中处理这些概念的方法: 参数化(Parameters) 在 Chisel 中,参数化是通过在模块构造函数中定…...
[Easy] leetcode-225/232 栈和队列的相互实现
一、用栈实现队列 1、题目 仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类:void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 …...

Springboot+Vue项目-基于Java+MySQL的个人云盘管理系统(附源码+演示视频+LW)
大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…...
Leetcode 116:填充每一个节点的下一个右侧节点指针
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到…...

AI智能分析赋能EasyCVR视频汇聚平台,为安全生产监管提供保障
一、背景需求 为提升公共及生产安全监管,深入贯彻落实中央关于智慧城市、数字乡村的部署要求,视频设备融合管理已成为视频治理的必然趋势。针对当前部分地区在视频监控系统建设中存在的问题,如重点地区视频监控系统建设零散、视频监控数据孤…...

Java设计模式 _结构型模式_外观模式
一、外观模式 1、外观模式 外观模式(Facade Pattern)是一种结构型模式。主要特点为隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这有助于降低系统的复杂性,提高可维护性。当客户端与多个子系统之间存在大量…...
数据结构之----栈与队列
栈是限定仅在表尾进行插入和删除操作的线性表; 队列是只允许在一端进行插入操作,而另一端进行删除操作的线性表; 栈,允许插入和删除的一端称为栈顶,另一端称为栈底,特点后进先出。 插入操作称为进栈&#…...

如何在windows server下安装mysql5.7数据库,并使用Navicat Premium 15可视化工具新建数据库并读取数据库信息。
如何在windows server下安装mysql5.7数据库? MySQL :: Download MySQL Community Server (Archived Versions)https://downloads.mysql.com/archives/community/点击↑,然后选择对应版本和平台↓下载 将下载后的安装包放入固定目录(这里以D:…...

Calendar 366 II for Mac v2.15.5激活版:智能日历管理软件
在繁忙的工作和生活中,如何高效管理日程成为了许多人的难题。Calendar 366 II for Mac,作为一款全方位的日历管理软件,以其独特的功能和优秀的用户体验,成为您的日程好帮手。 Calendar 366 II for Mac支持多种视图模式,…...

react引入阿里矢量库图标
react引入阿里矢量库图标 登录阿里矢量库,将项目所需的图标放一起 react项目中新建文件夹MyIcon.js 3. 在页面中引入,其中type为图标名称...

部署Gerapy
1.Gerapy 是什么? Gerapy 是一款基于 Python 3 的分布式爬虫管理框架,它旨在简化和优化分布式爬虫的部署、管理和监控过程。 2.作用与功能? 2.1分布式管理: Gerapy 允许用户在多台机器上部署和管理Scrapy爬虫,实现爬虫…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...