设计模式行为型——访问者模式
目录
访问者模式的定义
访问者模式的实现
访问者模式角色
访问者模式类图
访问者模式举例
访问者模式代码实现
访问者模式的特点
优点
缺点
使用场景
注意事项
实际应用
访问者模式的定义
访问者模式(Visitor Pattern)属于行为型设计模式,它允许在不修改现有对象结构的前提下,定义对这些对象执行操作的新操作。访问者模式将数据结构和操作分离,使得操作可以独立变化。
访问者模式基本思想是,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个 accept()方法来接受访问者对象的访问。不同的访问者对同一个元素的访问内容是不同,使得相同的元素集合可以产生不同的数据结果。
访问者模式的实现
访问者模式角色
- 抽象访问者角色(Visitor):接口或者抽象类,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
- 具体访问者角色(ConcreteVisitor):实现Visitor声明的接口,是每个操作实现的部分。
- 抽象元素角色(Element):接口或者抽象类,该类定义了一个接受访问者访问的方法 accept()方法,表示所有元素类型都支持被访问者访问。
- 具体元素角色(ConcreteElement):具体元素类型,实现了抽象元素(Element)所定义的接受操作接口。
- 结构对象角色(ObjectStructure):该类内部维护了元素集合,并提供方法接受访问者对该集合所有元素进行操作。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
访问者模式类图
访问者模式举例
访问者模式代码实现
抽象访问者角色
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 抽象访问者角色 * @date 2023/08/09 21:48:44*/
public interface ComputerPartVisitor {void visit(ComputerHost computerHost);void visit(Mouse mouse);void visit(Keyboard keyboard);void visit(Monitor monitor);
}
具体访问者角色
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 实体访问者角色 计算机部件显示访问者* @date 2023/08/09 21:54:19*/
public class ComputerPartDisplayVisitor implements ComputerPartVisitor{@Overridepublic void visit(ComputerHost computerHost) {System.out.println("Displaying Computer.");}@Overridepublic void visit(Mouse mouse) {System.out.println("Displaying Mouse.");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("Displaying Keyboard.");}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}
抽象元素角色
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 抽象元素角色 计算机组成部分* @date 2023/08/09 21:47:18*/
public interface ComputerPart {void accept(ComputerPartVisitor computerPartVisitor);
}
具体元素角色
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 具体元素角色 电脑主机* @date 2023/08/09 21:50:15*/
public class ComputerHost implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 具体元素角色 键盘* @date 2023/08/09 21:50:15*/
public class Keyboard implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 具体元素角色 显示器* @date 2023/08/09 21:50:15*/
public class Monitor implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 具体元素角色 鼠标* @date 2023/08/09 21:50:15*/
public class Mouse implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
结构对象角色
package com.common.demo.pattern.visitor;import java.util.ArrayList;
import java.util.List;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 结构对象角色 电脑* @date 2023/08/09 21:50:15*/
public class Computer{private List<ComputerPart> employeeList = new ArrayList<>();{employeeList.add(new ComputerHost());employeeList.add(new Keyboard());employeeList.add(new Monitor());employeeList.add(new Mouse());}//遍历public void showReport(ComputerPartVisitor visitor){for (ComputerPart computerPart : this.employeeList) {computerPart.accept(visitor);}}
}
测试代码
package com.common.demo.pattern.visitor;/*** @author Evan Walker 昂焱数据: https://www.ayshuju.com* @version 1.0* @desc 测试代码* @date 2023/08/09 22:00:44*/
public class Test {public static void main(String[] args) {Computer computer = new Computer();computer.showReport(new ComputerPartDisplayVisitor());}}
测试截图

访问者模式的特点
优点
- 增加新的操作更容易:通过访问者模式,可以在不修改现有对象结构的情况下增加新的操作,符合开闭原则。
- 将相关操作集中到一个访问者类中:访问者模式将相关操作封装在一个访问者类中,使得代码更加结构化和清晰。
- 扩展性强:由于访问者模式将数据结构和操作解耦,因此可以方便地添加新的数据结构和操作,扩展性强。
- 解耦性:解耦了数据结构与数据操作,使得操作集合可以独立变化。
缺点
- 增加新的元素类困难:当需要增加新的元素类时,需要同时修改访问者接口和所有的具体访问者类,可能导致修改的范围较大。
- 违反了单一职责原则:访问者模式将相关操作集中到访问者类中,可能导致该类承担过多的责任,违反单一职责原则。
- 违背依赖倒置原则:访问者角色依赖的是具体元素类型,而不是抽象。
使用场景
- 当需要对一组对象执行多种不同且不相关的操作时,可以考虑使用访问者模式。
- 数据结构稳定,数据结构与数据操作分离,作用于数据结构的操作经常变化的场景。
注意事项
- 对象结构稳定:在使用访问者模式时,对象结构应该是相对稳定的,避免频繁修改对象结构,否则会导致访问者接口和具体访问者类的修改范围较大。
- 具体元素类的扩展:如果需要频繁添加新的元素类,可能会增加访问者接口和具体访问者类的修改工作量,需要谨慎设计。
实际应用
- 编译器的语法树分析:编译器可以使用访问者模式来遍历语法树,对不同类型的节点执行不同的操作。
- 数据结构的序列化:对于复杂的数据结构,可以使用访问者模式来实现序列化操作,将对象转换为特定格式的字符串或字节流。
更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)
相关文章:
设计模式行为型——访问者模式
目录 访问者模式的定义 访问者模式的实现 访问者模式角色 访问者模式类图 访问者模式举例 访问者模式代码实现 访问者模式的特点 优点 缺点 使用场景 注意事项 实际应用 访问者模式的定义 访问者模式(Visitor Pattern)属于行为型设计模式&am…...
vue3官网文档学习、复习笔记(快速上手)
目录 2.Attribute 绑定(v-bind) 3.事件监听(v-on) 4.表单绑定(v-model) 5.条件渲染(v-if) 6.列表渲染(v-for) all.value all.value.filter(…...
0基础学习VR全景平台篇 第81篇:全景相机-临云镜如何直播推流
临云镜全景相机是阿里巴巴定制全景设备,实现空间三维信息的快速采集,与阿里云三维空间重建平台搭配,帮助品牌商与平台以较低的成本完成空间的快速采集,并支持对室内/室外空间的三维全景展示及空间漫游,同时支持VR浏览、…...
分数线划定
题目描述 查看题目信息 世博会志愿者的选拔工作正在A 市如火如荼的进行。为了选拔最合适的人才,A 市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。 面试分数线根据计划录取人数的150%划定,即如果计划录取m名志愿…...
考研C语言进阶题库——更新26-30题
目录 26.一个正整数,如果等于组成它的各个数字的阶数之和,该整数称为阶乘合数,例如1451阶加四阶加五阶,则145是一个三位阶乘合数,输入一个数,问共有多少个阶乘合数?(十万之内) 27.与2相关的数…...
用C语言实现定积分计算(包括无穷积分/可自定义精度)
关于严谨性的声明: 在用C语言进行定积分的计算之前,我需要声明以下几点: 一、我们所进行定积分计算的函数都是应当是黎曼可积的,这保证了我们即使均匀地分割区间也保证了积分的收敛性。 二、我们同时还应该认识到,鉴…...
使用Presto、Trino数据库时提示“The datetime zone id ‘GMT+08:00‘ is not recognised”
出现这个问题的原因是:Presto、Trino的驱动使用了joda这个库来处理时区的问题。但这个库的编写人似乎对java zone的格式没有太多经验。先看一下出错的代码: com.facebook.presto.jdbc.internal.joda.time.DateTimeZone#forID 根据String类型的zoneId转成…...
C# BeginInvoke 加 EndInvoke实现异步操作
1、定义一个委托 delegate long MyDel(int first, int second); 2、 需异步操作的函数 static int sum(int x,int y) {Console.WriteLine("InSide Sum1");Thread.Sleep(1000);Console.WriteLine("InSide Sum2");return x y;} 3、回调方法…...
“华为杯”研究生数学建模竞赛2015年-【华为杯】B题:数据的多流形结构分析(续)
目录 4.2.2 算法复杂度分析 4.2.3 参数影响 4.2.4 问题 3(a)求解 4.3 问题 3(b) 4.3.1 加权稀疏子空间聚类</...
R语言APSIM模型高级应用及批量模拟
随着数字农业和智慧农业的发展,基于过程的农业生产系统模型在模拟作物对气候变化的响应与适应、农田管理优化、作物品种和株型筛选、农田固碳和温室气体排放等领域扮演着越来越重要的作用。APSIM (Agricultural Production Systems sIMulator)模型是世界知名的作物生…...
【硬件设计】模拟电子基础三--集成运算放大电路
模拟电子基础三--集成运算放大电路 一、集成运算放大器1.1 定义、组成与性能1.2 电流源电路1.3 差动放大电路1.4 理想运算放大器 二、集成运算放大器的应用2.1 反向比例运算电路2.2 同向比例运算电路2.3 反向加法运算电路2.4 反向减法运算电路2.5 积分运算电路2.6 微分运算电路…...
JavaWeb(11)——前端综合案例5(小黑记事本)
一、实例需求 ⌛ 功能需求: ① 列表渲染 ② 删除功能 ③ 添加功能 ④ 底部统计 和 清空任务 二、代码实现 ☕ <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8" /> <meta http-equiv"X-UA-Compa…...
在使用TensorFlow的时候内部报错:内部某个方法或属性不存在
看到TensorFlow内部封装的方法报错的时候,我的第一反应是版本不匹配,立马去搜了对应版本,按照网上给的TensorFlow 2.2.0keras 2.3.1 python 3.7,反反复复安装、卸载、升级、降低版本了很多回还是八行,就在心态快要爆爆…...
dubbo之高可用
负载均衡 概述 负载均衡是指在集群中,将多个数据请求分散到不同的单元上执行,主要是为了提高系统的容错能力和对数据的处理能力。 Dubbo 负载均衡机制是决定一次服务调用使用哪个提供者的服务。 策略 在Dubbo中提供了7中负载均衡策略,默…...
gitee代码扫描js代码,降低复杂度,减少if-else判断的处理方法
把if-else换成如下形式 页面上的代码 <el-button id"btnSave" type"primary" :loading"loadingEdit" click"saveEdit(put,baseSet)"> {{ $t("formLabel.save") }} </el-button> methods代码: // 编…...
MySQL及SQL语句(3)
MySQL及SQL语句(3) 文章目录 MySQL及SQL语句(3)一、多表查询1.1 准备sql1.2 笛卡尔积1.3 多表查询的分类:内连接查询外连接查询子查询多表查询练习 二、事务2.1 事务的基本介绍概念操作实例事务提交的两种方式 2.2 事务的四大特征原子性持久性隔离性一致性 2.3 事务…...
MySQL 查询语句大全
目录 基础查询 直接查询 AS起别名 去重(复)查询 条件查询 算术运算符查询 逻辑运算符查询 正则表达式查询⭐ 模糊查询 范围查询 是否非空判断查询 排序查询 限制查询(分页查询) 随机查询 分组查询 HAVING 高级查询…...
【Axure高保真原型】账单列表和详情
今天和大家分享账单列表和详情的原型模板,点击月份可以展开或收起对应的菜单列表,该模板是用中继器制作的,在中继器里填写数据后,自动计算出支出和收入总和,点击订单,可以查看该订单的详情。 【原型效果】…...
嵌入式面试题1
1 读程序段,回答问题 int main(int argc, char *argv[]) { int c 9, d 0; c c % 5; d c; printf("d%d\n",d);return 0;} a) 写出程序输出 b) 在一个可移植的系统中这种表达式是否存在风险?why? 答: 1.程序输出为:…...
base64转二进制流,file文件
base64转二进制流 img标签src属性,可以直接使用base64字符串,base64需要先解码,然后再转为流 /*** Base64字符串转二进制流* param {String} dataurl Base64字符串(字符串包含Data URI scheme,例如:data:image/png;b…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
