当前位置: 首页 > news >正文

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、访问者模式 在访问者模式中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。通过这种方式&#xff0c;元素的执行算法可以随 着访问者改变而…...

想要通过软件测试的面试,都需要学习哪些知识

很多人认为&#xff0c;软件测试是一个简单的职位&#xff0c;职业生涯走向也不会太好&#xff0c;但是随着时间的推移&#xff0c;软件测试行业的变化&#xff0c;人们开始对软件测试行业的认知有了新的高度&#xff0c;越来越多的人开始关注这个行业&#xff0c;开始重视这个…...

MySQL的索引使用的数据结构,事务知识

一、索引的数据结构&#x1f338; 索引的数据结构&#xff08;非常重要&#xff09; mysql的索引的数据结构&#xff0c;并非定式&#xff01;&#xff01;&#xff01;取决于MySQL使用哪个存储引擎 数据库这块组织数据使用的数据结构是在硬盘上的。我们平时写的代码是存在内存…...

普及100Hz高刷+1ms响应 微星发布27寸显示器:仅售799元

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

Java课题笔记~6个重要注解参数含义

1、[掌握]Before 前置通知-方法有 JoinPoint 参数 在目标方法执行之前执行。被注解为前置通知的方法&#xff0c;可以包含一个 JoinPoint 类型参数。 该类型的对象本身就是切入点表达式。通过该参数&#xff0c;可获取切入点表达式、方法签名、目标对象等。 不光前置通知的方…...

Windows Docker Desk环境时区问题导致的时间问题解决?

大多docker镜像为了保持镜像大小&#xff0c;采用了alpine linux。 但经常由于时区问题导致时间不准确&#xff0c;解决也很简单。 1.查看事件文件 cd /usr/share/zoneinfo 2.复制时区文件 将文件copy到 /etc/localtime 路径下即可&#xff08;重庆时区&#xff0c;上海也…...

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 的简写&#xff0c;译为“控制反转”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;是一个重要的面向对象编程法则。 Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化&#xff0c;控制对象与对象之间的依赖关系。…...

安卓下模拟渲染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)

官网&#xff1a; vue3&#xff1a;https://cn.vuejs.org/ vue2&#xff1a;https://v2.cn.vuejs.org/v2/guide/ 简单上手&#xff1a; 流程&#xff1a; 导入开发版本的Vue.js <!--开发环境版本&#xff0c;包含了有帮助的命令行警告--> <script src"https…...

C++初阶语法——命名空间

前言&#xff1a;C&#xff0c;即cplusplus&#xff0c;顾名思义&#xff0c;是C语言promax版本&#xff0c;C兼容C语言。 C的诞生是因为贝尔实验室的本贾尼等大佬认为C语言的语法坑实在太多&#xff0c;拥有许多不足之处&#xff08;比如命名冲突&#xff0c;&#xff09;&…...

Axwing.878 线性同余方程

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

【Pytorch+torchvision】MNIST手写数字识别

深度学习入门项目&#xff0c;含代码详细解析 在本文中&#xff0c;我们将在PyTorch中构建一个简单的卷积神经网络&#xff0c;并使用MNIST数据集训练它识别手写数字。 MNIST包含70,000张手写数字图像: 60,000张用于培训&#xff0c;10,000张用于测试。图像是灰度&#xff08;即…...

spring boot 集成rocketmq

集成Spring Boot和RocketMQ 在现代的微服务架构中&#xff0c;消息队列已经成为一种常见的异步处理模式&#xff0c;它能解决服务间的同步调用、耦合度高、流量高峰等问题。RocketMQ是阿里巴巴开源的一款消息中间件&#xff0c;性能优秀&#xff0c;功能齐全&#xff0c;被广泛…...

redis Hash类型命令

Redis中的Hash类型有多个常用命令可用于对Hash键进行操作。以下是一些常见的Redis Hash类型命令&#xff1a; HSET&#xff1a;设置Hash字段的值。 它将指定字段与相应的值关联起来&#xff0c;如果字段已经存在&#xff0c;则更新其值&#xff0c;如果字段不存在&#xff0c…...

P1194 买礼物(最小生成树)(内附封面)

买礼物 题目描述 又到了一年一度的明明生日了&#xff0c;明明想要买 B B B 样东西&#xff0c;巧的是&#xff0c;这 B B B 样东西价格都是 A A A 元。 但是&#xff0c;商店老板说最近有促销活动&#xff0c;也就是&#xff1a; 如果你买了第 I I I 样东西&#xff0…...

oracle基础语法和备份恢复

Oracle总结 sql命令分类 1.DDL&#xff0c;数据定义语言&#xff0c;create创建/drop销毁 2.DCL&#xff0c;数据库控制语言&#xff0c;grant授权/revoke撤销 3.DML&#xff0c;数据操纵语言&#xff0c;insert/update/delete等sql语句 4.DQL&#xff0c;数据查询语言&am…...

【MATLAB第66期】#源码分享 | 基于MATLAB的PAWN全局敏感性分析模型(有条件参数和无条件参数)

【MATLAB第66期】#源码分享 | 基于MATLAB的PAWN全局敏感性分析模型&#xff08;有条件参数和无条件参数&#xff09; 文献参考 Pianosi, F., Wagener, T., 2015. A simple and efficient method for global sensitivity analysis based on cumulative distribution functions.…...

vue2过渡vue3技术差异点指南

基础点 reactive() 定义响应式变量(仅仅引用类型有效&#xff1a;对象数组map&#xff0c;set)&#xff1a;reactive(),类似于data中return的数据 例子&#xff1a; import { reactive } from vueexport default {setup() {const state reactive({ count: 0 })function in…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)

第一篇&#xff1a;Liunx环境下搭建PaddlePaddle 3.0基础环境&#xff08;Liunx Centos8.5安装Python3.10pip3.10&#xff09; 一&#xff1a;前言二&#xff1a;安装编译依赖二&#xff1a;安装Python3.10三&#xff1a;安装PIP3.10四&#xff1a;安装Paddlepaddle基础框架4.1…...