Go和Java实现访问者模式
Go和Java实现访问者模式
我们下面通过一个解压和压缩各种类型的文件的案例来说明访问者模式的使用。
1、访问者模式
在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随
着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者
对象就可以处理元素对象上的操作。
-
意图:主要将数据结构与数据操作分离。
-
主要解决:稳定的数据结构和易变的操作耦合问题。
-
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这
些对象的类,使用访问者模式将这些封装到类中。
-
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
-
关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。
-
应用实例:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一
个判断,这就是访问者模式。
-
优点:1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
-
缺点:1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒
置原则,依赖了具体类,没有依赖抽象。
-
使用场景:1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一
个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希
望在增加新操作时修改这些类。
-
注意事项:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。
-
适用性:
一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
需要对一个对象结构中的对象进行很多不同的并且不相关的操作,让你想避免让这些操作污染这些对象的类。
Visitor使得你可以将相关的操作集中起来定义在一个类中,当该对象结构被很多应用共享时,用Visitor模
式让每个应用仅包含需要用到的操作。
定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者
的接口,这可能想要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
2、Go实现访问者模式
package visitor// ========== 访问者FileUseVisitor ==========
type FileUseVisitor interface {// 为每一个类声明一个visit操作visitPdfFile(FileResourceVisitable)visitPPTFile(FileResourceVisitable)visitTextFile(FileResourceVisitable)
}
package visitorimport "fmt"// ========== 访问者Compress ==========
type Compress struct {
}func (compress *Compress) visitPdfFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Compress file: " + fileResourceVisitable.(*PdfFile).Path)
}func (compress *Compress) visitPPTFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Compress file: " + fileResourceVisitable.(*PPTFile).Path)
}func (compress *Compress) visitTextFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Compress file: " + fileResourceVisitable.(*TextFile).Path)
}
package visitorimport "fmt"// ========== 访问者Decompress ==========
type Decompress struct {
}func (decompress *Decompress) visitPdfFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Decompress file: " + fileResourceVisitable.(*PdfFile).Path)
}func (decompress *Decompress) visitPPTFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Decompress file: " + fileResourceVisitable.(*PPTFile).Path)
}func (decompress *Decompress) visitTextFile(fileResourceVisitable FileResourceVisitable) {fmt.Println("Decompress file: " + fileResourceVisitable.(*TextFile).Path)
}
package visitor// ========== 接收者FileResourceVisitable ==========
type FileResourceVisitable interface {accept(FileUseVisitor)
}
package visitor// ========== 接收者PdfFile ==========
type PdfFile struct {Path string
}func (pdfFile *PdfFile) accept(fileUseVisitor FileUseVisitor) {fileUseVisitor.visitPdfFile(pdfFile)
}
package visitor// ========== 接收者PPTFile ==========
type PPTFile struct {Path string
}func (pPTFile *PPTFile) accept(fileUseVisitor FileUseVisitor) {fileUseVisitor.visitPPTFile(pPTFile)
}
package visitor// ========== 接收者TextFile ==========
type TextFile struct {Path string
}func (textFile *TextFile) accept(fileUseVisitor FileUseVisitor) {fileUseVisitor.visitTextFile(textFile)
}
package visitor// ========== FileStructure ==========
type FileStructure struct {fileResourceVisitableList []FileResourceVisitable
}func (fileStructure *FileStructure) Attach(fileResourceVisitable FileResourceVisitable) {fileStructure.fileResourceVisitableList = append(fileStructure.fileResourceVisitableList, fileResourceVisitable)
}func (fileStructure *FileStructure) Detach(fileResourceVisitable FileResourceVisitable) {for i := 0; i < len(fileStructure.fileResourceVisitableList); i++ {if fileStructure.fileResourceVisitableList[i] == fileResourceVisitable {fileStructure.fileResourceVisitableList = append(fileStructure.fileResourceVisitableList[:i], fileStructure.fileResourceVisitableList[i+1:]...)}}
}func (fileStructure *FileStructure) Accept(fileUseVisitor FileUseVisitor) {for _, fileResourceVisitable := range fileStructure.fileResourceVisitableList {fileResourceVisitable.accept(fileUseVisitor)}
}
package mainimport . "proj/visitor"func main() {fileStructure := FileStructure{}fileStructure.Attach(&PPTFile{Path: "test.ppt"})fileStructure.Attach(&PdfFile{Path: "test.pdf"})fileStructure.Attach(&TextFile{Path: "test.txt"})fileStructure.Accept(&Decompress{})fileStructure.Accept(&Compress{})
}
# 输出
Decompress file: test.ppt
Decompress file: test.pdf
Decompress file: test.txt
Compress file: test.ppt
Compress file: test.pdf
Compress file: test.txt
3、Java实现访问者模式
package com.visitor;// ========== 访问者FileUseVisitor ==========
public interface FileUseVisitor {// 为每一个类声明一个visit操作void visitPdfFile(FileResourceVisitable fileResourceVisitable);void visitPPTFile(FileResourceVisitable fileResourceVisitable);void visitTextFile(FileResourceVisitable fileResourceVisitable);
}
package com.visitor;// ========== 访问者Compress ==========
public class Compress implements FileUseVisitor{@Overridepublic void visitPdfFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Compress file: "+fileResourceVisitable.path);}@Overridepublic void visitPPTFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Compress file: "+fileResourceVisitable.path);}@Overridepublic void visitTextFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Compress file: "+fileResourceVisitable.path);}
}
package com.visitor;// ========== 访问者Decompress ==========
public class Decompress implements FileUseVisitor{@Overridepublic void visitPdfFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Decompress file: "+fileResourceVisitable.path);}@Overridepublic void visitPPTFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Decompress file: "+fileResourceVisitable.path);}@Overridepublic void visitTextFile(FileResourceVisitable fileResourceVisitable) {System.out.println("Decompress file: "+fileResourceVisitable.path);}
}
package com.visitor;// ========== 接收者FileResourceVisitable ==========
public abstract class FileResourceVisitable {protected String path;abstract void accept(FileUseVisitor fileUseVisitor);
}
package com.visitor;// ========== 接收者PdfFile ==========
public class PdfFile extends FileResourceVisitable {public PdfFile(String path){this.path = path;}@Overridepublic void accept(FileUseVisitor fileUseVisitor) {fileUseVisitor.visitPdfFile(this);}
}
package com.visitor;// ========== 接收者PPTFile ==========
public class PPTFile extends FileResourceVisitable {public PPTFile(String path){this.path = path;}@Overridepublic void accept(FileUseVisitor fileUseVisitor) {fileUseVisitor.visitPPTFile(this);}
}
package com.visitor;// ========== 接收者TextFile ==========
public class TextFile extends FileResourceVisitable {public TextFile(String path){this.path = path;}@Overridepublic void accept(FileUseVisitor fileUseVisitor) {fileUseVisitor.visitTextFile(this);}
}
package com.visitor;import java.util.ArrayList;
import java.util.List;
import java.util.Objects;// ========== FileStructure ==========
public class FileStructure {List<FileResourceVisitable> fileResourceVisitableList = new ArrayList<>();public void attach(FileResourceVisitable fileResourceVisitable){fileResourceVisitableList.add(fileResourceVisitable);}public void detach(FileResourceVisitable fileResourceVisitable){Objects.requireNonNull(fileResourceVisitable);}public void accept(FileUseVisitor fileUseVisitor){for(FileResourceVisitable fileResourceVisitable:fileResourceVisitableList){fileResourceVisitable.accept(fileUseVisitor);}}
}
package com.visitor;public class Test {public static void main(String[] args) {FileStructure fileStructure = new FileStructure();fileStructure.attach(new PPTFile("test.pdf"));fileStructure.attach(new PdfFile("test.pdf"));fileStructure.attach(new TextFile("test.txt"));fileStructure.accept(new Compress());fileStructure.accept(new Decompress());}
}
# 输出
Compress file: test.pdf
Compress file: test.pdf
Compress file: test.txt
Decompress file: test.pdf
Decompress file: test.pdf
Decompress file: test.txt
相关文章:
Go和Java实现访问者模式
Go和Java实现访问者模式 我们下面通过一个解压和压缩各种类型的文件的案例来说明访问者模式的使用。 1、访问者模式 在访问者模式中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随 着访问者改变而…...
想要通过软件测试的面试,都需要学习哪些知识
很多人认为,软件测试是一个简单的职位,职业生涯走向也不会太好,但是随着时间的推移,软件测试行业的变化,人们开始对软件测试行业的认知有了新的高度,越来越多的人开始关注这个行业,开始重视这个…...

MySQL的索引使用的数据结构,事务知识
一、索引的数据结构🌸 索引的数据结构(非常重要) mysql的索引的数据结构,并非定式!!!取决于MySQL使用哪个存储引擎 数据库这块组织数据使用的数据结构是在硬盘上的。我们平时写的代码是存在内存…...

普及100Hz高刷+1ms响应 微星发布27寸显示器:仅售799元
不论办公还是游戏,高刷及低响应时间都很重要,微星现在推出了一款27寸显示器PRO MP273A, 售价只有799元,但支持100Hz高刷、1ms响应时间,还有FreeSync技术减少撕裂。 PRO MP273A的100Hz高刷新率是其最大的卖点之一&#…...

Java课题笔记~6个重要注解参数含义
1、[掌握]Before 前置通知-方法有 JoinPoint 参数 在目标方法执行之前执行。被注解为前置通知的方法,可以包含一个 JoinPoint 类型参数。 该类型的对象本身就是切入点表达式。通过该参数,可获取切入点表达式、方法签名、目标对象等。 不光前置通知的方…...
Windows Docker Desk环境时区问题导致的时间问题解决?
大多docker镜像为了保持镜像大小,采用了alpine linux。 但经常由于时区问题导致时间不准确,解决也很简单。 1.查看事件文件 cd /usr/share/zoneinfo 2.复制时区文件 将文件copy到 /etc/localtime 路径下即可(重庆时区,上海也…...

SpringBoot复习:(22)ConfigurationProperties和@PropertySource配合使用及JSR303校验
一、配置类 package cn.edu.tju.config;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component;Component ConfigurationPropertie…...
Spring IoC (控制反转)
IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则。 Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。…...
安卓下模拟渲染EGLImageKHR
创建AHardwareBuffer并填充颜色 AHardwareBuffer_Desc desc = {static_cast<uint32_t>(screenW),static_cast<uint32_t>(screenH),...
Spring MVC 框架学习总结
文章目录 初步认识 Spring MVC 框架 一、初识 Spring MVC 框架 二、 三、 四、 五、 六、 七、 八、 九、...
2、简单上手+el挂载点+v-xx(v-text、v-html、v-on、v-show、v-if、v-bind、v-for)
官网: vue3:https://cn.vuejs.org/ vue2:https://v2.cn.vuejs.org/v2/guide/ 简单上手: 流程: 导入开发版本的Vue.js <!--开发环境版本,包含了有帮助的命令行警告--> <script src"https…...

C++初阶语法——命名空间
前言:C,即cplusplus,顾名思义,是C语言promax版本,C兼容C语言。 C的诞生是因为贝尔实验室的本贾尼等大佬认为C语言的语法坑实在太多,拥有许多不足之处(比如命名冲突,)&…...

Axwing.878 线性同余方程
题目 给定n组数据ai, bi , mi,对于每组数求出一个xi,使其满足ai * xibi (mod mi),如果无解则输出impossible。 输入格式 第一行包含整数n。 接下来n行,每行包含一组数据ai , bi , mi。 输出格式 输出共n行,每组数…...

【Pytorch+torchvision】MNIST手写数字识别
深度学习入门项目,含代码详细解析 在本文中,我们将在PyTorch中构建一个简单的卷积神经网络,并使用MNIST数据集训练它识别手写数字。 MNIST包含70,000张手写数字图像: 60,000张用于培训,10,000张用于测试。图像是灰度(即…...
spring boot 集成rocketmq
集成Spring Boot和RocketMQ 在现代的微服务架构中,消息队列已经成为一种常见的异步处理模式,它能解决服务间的同步调用、耦合度高、流量高峰等问题。RocketMQ是阿里巴巴开源的一款消息中间件,性能优秀,功能齐全,被广泛…...
redis Hash类型命令
Redis中的Hash类型有多个常用命令可用于对Hash键进行操作。以下是一些常见的Redis Hash类型命令: HSET:设置Hash字段的值。 它将指定字段与相应的值关联起来,如果字段已经存在,则更新其值,如果字段不存在,…...

P1194 买礼物(最小生成树)(内附封面)
买礼物 题目描述 又到了一年一度的明明生日了,明明想要买 B B B 样东西,巧的是,这 B B B 样东西价格都是 A A A 元。 但是,商店老板说最近有促销活动,也就是: 如果你买了第 I I I 样东西࿰…...
oracle基础语法和备份恢复
Oracle总结 sql命令分类 1.DDL,数据定义语言,create创建/drop销毁 2.DCL,数据库控制语言,grant授权/revoke撤销 3.DML,数据操纵语言,insert/update/delete等sql语句 4.DQL,数据查询语言&am…...

【MATLAB第66期】#源码分享 | 基于MATLAB的PAWN全局敏感性分析模型(有条件参数和无条件参数)
【MATLAB第66期】#源码分享 | 基于MATLAB的PAWN全局敏感性分析模型(有条件参数和无条件参数) 文献参考 Pianosi, F., Wagener, T., 2015. A simple and efficient method for global sensitivity analysis based on cumulative distribution functions.…...
vue2过渡vue3技术差异点指南
基础点 reactive() 定义响应式变量(仅仅引用类型有效:对象数组map,set):reactive(),类似于data中return的数据 例子: import { reactive } from vueexport default {setup() {const state reactive({ count: 0 })function in…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...