设计模式二十四:访问者模式(Visitor Pattern)
用于将数据结构与数据操作分离,使得可以在不修改数据结构的情况下,定义新的操作。访问者模式的核心思想是,将数据结构和操作进行解耦,从而使得新增操作时不必修改数据结构,只需添加新的访问者。主要目的是在不改变数据结构的情况下,为数据结构中的元素添加新的操作,从而满足开闭原则(对扩展开放,对修改封闭)
访问者模式使用场景
- 数据结构稳定,但操作频繁变化
当数据结构相对稳定,但经常需要新增或修改不同类型的操作时,访问者模式可以将操作与数据结构分离,使得新增操作不影响现有的数据结构 - 操作多态性
当存在一组不同类型的元素,每个元素需要支持不同类型的操作时,访问者模式可以将操作封装成具体访问者类,每个具体访问者类负责一种操作 - 避免污染数据结构
当希望在不改变现有数据结构的前提下,向数据结构中添加新的操作时,访问者模式可以避免污染数据结构。 - 扩展性要求高
当需要添加新类型的元素或操作时,访问者模式使得扩展变得相对容易,只需要新增具体元素类和具体访问者类。 - 解耦操作和数据结构
当数据结构和操作之间的耦合度较高时,访问者模式可以解耦这两者,使得各自可以独立变化。 - 复杂的对象结构
当对象结构非常复杂,且其中的元素类型较多时,通过访问者模式可以将不同类型的操作分布到不同的具体访问者类中,使代码更加清晰
访问者模式的主要角色
- 访问者(Visitor):
定义了对数据结构中各个元素进行访问的抽象方法,每个方法对应一个具体元素的操作。访问者接口可能会定义多个访问方法,每个方法处理不同类型的元素。 - 具体访问者(Concrete Visitor):
实现了访问者接口中定义的方法,对具体的元素进行操作。 - 元素(Element):
定义了一个accept方法,该方法接受一个访问者对象作为参数,将自身传递给访问者,使访问者可以对自己进行操作。 - 具体元素(Concrete Element):
实现了元素接口的accept方法,将自身传递给访问者,以便访问者可以对自己进行操作。 - 对象结构(Object Structure):
维护一个元素的集合,提供了迭代元素的方法,通常可以使用集合类来实现。
java代码实例
元素
public interface Animal {void accept(AnimalVisitor animalVisitor );}
具体元素
// 具体动物类
class Lion implements Animal {@Overridepublic void accept(AnimalVisitor visitor) {visitor.visitLion(this);}
}class Elephant implements Animal {@Overridepublic void accept(AnimalVisitor visitor) {visitor.visitElephant(this);}
}class Dolphin implements Animal {@Overridepublic void accept(AnimalVisitor visitor) {visitor.visitDolphin(this);}
}
访问者接口
public interface AnimalVisitor {//拜访狮子void visitLion(Lion lion);//拜访大象void visitDolphin(Dolphin dolphin);//拜访海豚void visitElephant(Elephant elephant);}
具体访问者
//动物清洁工
public class AnimalCleaningVisitor implements AnimalVisitor{@Overridepublic void visitLion(Lion lion) {System.out.println("cleaning the lion's enclosure");}@Overridepublic void visitDolphin(Dolphin dolphin) {System.out.println("cleaning the dolphin's enclosure");}@Overridepublic void visitElephant(Elephant elephant) {System.out.println("cleaning the elephant's enclosure");}
}//动物饲养员
public class AnimalFeedingVisitor implements AnimalVisitor{@Overridepublic void visitLion(Lion lion) {System.out.println("Feeding the lion's,ying-ying-ying");}@Overridepublic void visitDolphin(Dolphin dolphin) {System.out.println("Feeding the dolphin's,ying-ying-ying");}@Overridepublic void visitElephant(Elephant elephant) {System.out.println("Feeding the elephant's,ying-ying-ying");}
}
客户端
public static void main(String[] args) {Animal[] animals = new Animal[]{ new Lion(), new Elephant(), new Dolphin() };AnimalVisitor feedingVisitor = new AnimalFeedingVisitor();AnimalVisitor cleaningVisitor = new AnimalCleaningVisitor();for (Animal animal : animals) {animal.accept(feedingVisitor);animal.accept(cleaningVisitor);}}
输出
Feeding the lion's,ying-ying-ying
cleaning the lion's enclosure
Feeding the elephant's,ying-ying-ying
cleaning the elephant's enclosure
Feeding the dolphin's,ying-ying-ying
cleaning the dolphin's enclosure
访问者模式优缺点
访问者模式适用于某些特定的场景,特别是在操作和数据结构之间的耦合性较高,且数据结构相对稳定的情况下。在使用访问者模式时,需要权衡其优点和缺点,并根据实际需求进行选择。
优点
- 新增操作容易
访问者模式使得新增操作变得相对容易,只需要新增一个新的访问者类,而无需修改现有的元素类。 - 解耦操作和数据结构
访问者模式将操作(访问者类)与数据结构(元素类)解耦,使得操作可以独立变化,不影响数据结构 - 增加灵活性
可以在不改变数据结构的情况下,对数据结构中的元素进行不同类型的操作,从而增加了灵活性。 - 符合单一职责原则
访问者模式将具体操作封装到具体访问者类中,符合单一职责原则,使得每个类的职责更加清晰。 - 适用于稳定的数据结构
访问者模式适用于数据结构相对稳定,而操作需要频繁变化的场景
缺点
- 增加类的数量
访问者模式引入了多个具体访问者类,可能会增加类的数量,使得代码变得复杂 - 破坏封装性
访问者模式需要元素类暴露接受访问者的方法,这可能会破坏元素类的封装性 - 增加扩展难度
新增一种元素类型时,需要修改所有具体访问者类,这可能会增加扩展的难度。 - 不适用于元素变化频繁的场景
如果元素的类型经常变化,频繁新增元素,使用访问者模式可能会增加维护成本 - 不适用于简单场景
在简单的场景下,使用访者模式可能会引入不必要的复杂性
相关文章:
设计模式二十四:访问者模式(Visitor Pattern)
用于将数据结构与数据操作分离,使得可以在不修改数据结构的情况下,定义新的操作。访问者模式的核心思想是,将数据结构和操作进行解耦,从而使得新增操作时不必修改数据结构,只需添加新的访问者。主要目的是在不改变数据…...
使用gn+Ninja构建项目
使用下载编译好的gn和ninja报错 先下载了gn的源码[gn.googlesource.com/gn],然后编译报错,就直接下载了了编译号的gn和Ninja,然后写了Helloworld应用的BUILD.gn,然后将"gn\examples\simple_build\build"拷贝至当前目录…...
VMware虚拟机连不上网络
固定ip地址 进入网络配置文件 cd /etc/sysconfig/network-scripts 打开文件 vi ifcfg-ens33 编辑 BOOTPROTO设置为static,有3个值(decp、none、static) BOOTPROTO"static" 打开网络 ONBOOT"yes" 固定ip IPADDR1…...
安防视频监控/视频集中存储/云存储平台EasyCVR平台无法取消共享通道该如何解决?
视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等,视频智能分析平台EasyCVR融合性强、开放度…...
算法通关村-----如何基于数组和链表实现栈
实现栈的基本方法 push(T t)元素入栈 T pop() 元素出栈 Tpeek() 查看栈顶元素 boolean isEmpty() 栈是否为空 基于数组实现栈 import java.util.Arrays;public class ArrayStack<T> {private Object[] stack;private int top;public ArrayStack() {this.stack new…...
day-05 TCP半关闭 ----- DNS ----- 套接字的选项
一、优雅的断开套接字连接 之前套接字的断开都是单方面的。 (一)基于TCP的半关闭 Linux的close函数和windows的closesocket函数意味着完全断开连接。完全断开不仅不能发送数据,从而也不能接收数据。在某些情况下,通信双方的某一方…...
区块链金融项目怎么做?
区块链技术的兴起引发了金融领域的变革,为金融行业带来了前所未有的机遇与挑战。在这个快速发展的领域中,如何在区块链金融领域做出卓越的表现?本文将从专业性和思考深度两个方面,探讨区块链金融的发展路径,并为读者提…...
Redis与数据库保持一致
参考链接 先更新数据库,再更新redis 存在漏洞,如果更新Redis失败,仍然会导致不一致 先删Redis,再更新数据库并同步数据到Redis 存在漏洞,多线程情况下,线程1删除redis后,还是有可能被其他线程读取旧的数据…...
idea中vue项目 npm安装插件后node modules中找不到
从硬盘中重新加载一下...
已知两地经纬度,计算两地直线距离
文章目录 1 原理公式2 代码实现2.1 JavaScript2.2 C2.3 Python2.4 MATLAB 1 原理公式 在地球上,计算两点之间的直线距离通常使用地理坐标系(例如WGS84)。计算两地直线距离的公式是根据经纬度之间的大圆距离(Great Circle Distanc…...
我想开通期权?如何开通期权账户?
场内期权的合约由交易所统一标准化定制,大家面对的同一个合约对应的价格都是一致的,比较公开透明,期权开户当天不能交易的,期权开户需要满足20日日均50万及半年交易经验即可操作,下文科普我想开通期权?如何…...
ChatGPT对软件测试的影响
ChatGPT 是一个经过预训练的 AI 语言模型,可以通过聊天的方式回答问题,或者与人闲聊。它能处理的是文本类的信息,输出也只能是文字。它从我们输入的信息中获取上下文,结合它被训练的大模型,进行分析总结,给…...
minion在ubuntu上的搭建步骤
在Ubuntu上搭建MinIO可以按照以下步骤进行: 下载MinIO服务器二进制文件: 通过浏览器访问 https://min.io/download 或使用以下命令获取最新的MinIO二进制文件:wget https://dl.min.io/server/minio/release/linux-amd64/minio赋予二进制文件…...
Leetcode刷题笔记--Hot31-40
1--颜色分类(75) 主要思路: 快排 #include <iostream> #include <vector>class Solution { public:void sortColors(std::vector<int>& nums) {quicksort(nums, 0, nums.size()-1);}void quicksort(std::vector<int…...
【Python】环境配置,【Pytorch】GPU版本安装
总结: 使用conda新建切换环境,然后使用pip安装卸载包 【python】pip conda_conda list没有pytorch_myaijarvis的博客-CSDN博客 pip换源 https://blog.csdn.net/maotenghua/article/details/104188086 在当前用户目录下创建pip目录,即C:\U…...
BEVFusion复现 (Ubuntu RTX3090)
https://github.com/ADLab-AutoDrive/BEVFusion 1.环境安装 我的机器是RTX3090,CUDA11.1 1.创建虚拟环境 conda create -n bevfusion python3.8.3 2.安装PyTorch 和 torchvision pip install torch1.8.0cu111 torchvision0.9.0cu111 torchaudio0.8.0 -f https://…...
Python基础知识学习与回顾
Python学习 Python基本语法 标识符 标识符由数字、字符串、下划线构成。 注意事项: 标识符不以数字开头区分大小写下划线开头的标识符具有特殊意义保留字,Python保留了一些关键字,这些关键字都是通过小写字母进行保存。 下划线开头的特…...
SpringBoot笔记——(狂神说)——待续
路线 javase: OOPmysql:持久化 htmlcssjsjquery框架:视图,框架不熟练,css不好; javaweb:独立开发MVC三层架构的网站了∶原始 ssm :框架:简化了我们的开发流程,配置也开始较为复杂; war: tomcat运行 spring再简化: SpringBoot - jar:内嵌tomca…...
Linux TCP编程流程
一、TCP编程流程 TCP 提供的是面向连接的、可靠的、字节流服务。TCP的服务器端和客户端编程流程如下: 1.socket()方法 用来创建一个套接字,有了套接字就可以通过网络进行数据的收发。这也是为什么进行网络通信的程序首先要创建一个套接字。创建套接字时…...
pyqt5 QuickStart
在使用pyqt5之前,建议下载一个Anaconda环境,这样下载python包更方便,本篇文章是建立在已经安装好Anaconda的情况下使用的。IDE就是标准的PyCharm了。 一、pyqt包的安装 python终端执行下面两个安装命令: pip install PyQt5 pip …...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
