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

设计模式二十四:访问者模式(Visitor Pattern)

用于将数据结构与数据操作分离,使得可以在不修改数据结构的情况下,定义新的操作。访问者模式的核心思想是,将数据结构和操作进行解耦,从而使得新增操作时不必修改数据结构,只需添加新的访问者。主要目的是在不改变数据结构的情况下,为数据结构中的元素添加新的操作,从而满足开闭原则(对扩展开放,对修改封闭)

访问者模式使用场景

  1. 数据结构稳定,但操作频繁变化
    当数据结构相对稳定,但经常需要新增或修改不同类型的操作时,访问者模式可以将操作与数据结构分离,使得新增操作不影响现有的数据结构
  2. 操作多态性
    当存在一组不同类型的元素,每个元素需要支持不同类型的操作时,访问者模式可以将操作封装成具体访问者类,每个具体访问者类负责一种操作
  3. 避免污染数据结构
    当希望在不改变现有数据结构的前提下,向数据结构中添加新的操作时,访问者模式可以避免污染数据结构。
  4. 扩展性要求高
    当需要添加新类型的元素或操作时,访问者模式使得扩展变得相对容易,只需要新增具体元素类和具体访问者类。
  5. 解耦操作和数据结构
    当数据结构和操作之间的耦合度较高时,访问者模式可以解耦这两者,使得各自可以独立变化。
  6. 复杂的对象结构
    当对象结构非常复杂,且其中的元素类型较多时,通过访问者模式可以将不同类型的操作分布到不同的具体访问者类中,使代码更加清晰

访问者模式的主要角色

  1. 访问者(Visitor):
    定义了对数据结构中各个元素进行访问的抽象方法,每个方法对应一个具体元素的操作。访问者接口可能会定义多个访问方法,每个方法处理不同类型的元素。
  2. 具体访问者(Concrete Visitor):
    实现了访问者接口中定义的方法,对具体的元素进行操作。
  3. 元素(Element):
    定义了一个accept方法,该方法接受一个访问者对象作为参数,将自身传递给访问者,使访问者可以对自己进行操作。
  4. 具体元素(Concrete Element):
    实现了元素接口的accept方法,将自身传递给访问者,以便访问者可以对自己进行操作。
  5. 对象结构(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

访问者模式优缺点

访问者模式适用于某些特定的场景,特别是在操作和数据结构之间的耦合性较高,且数据结构相对稳定的情况下。在使用访问者模式时,需要权衡其优点和缺点,并根据实际需求进行选择。
优点

  1. 新增操作容易
    访问者模式使得新增操作变得相对容易,只需要新增一个新的访问者类,而无需修改现有的元素类。
  2. 解耦操作和数据结构
    访问者模式将操作(访问者类)与数据结构(元素类)解耦,使得操作可以独立变化,不影响数据结构
  3. 增加灵活性
    可以在不改变数据结构的情况下,对数据结构中的元素进行不同类型的操作,从而增加了灵活性。
  4. 符合单一职责原则
    访问者模式将具体操作封装到具体访问者类中,符合单一职责原则,使得每个类的职责更加清晰。
  5. 适用于稳定的数据结构
    访问者模式适用于数据结构相对稳定,而操作需要频繁变化的场景

缺点

  1. 增加类的数量
    访问者模式引入了多个具体访问者类,可能会增加类的数量,使得代码变得复杂
  2. 破坏封装性
    访问者模式需要元素类暴露接受访问者的方法,这可能会破坏元素类的封装性
  3. 增加扩展难度
    新增一种元素类型时,需要修改所有具体访问者类,这可能会增加扩展的难度。
  4. 不适用于元素变化频繁的场景
    如果元素的类型经常变化,频繁新增元素,使用访问者模式可能会增加维护成本
  5. 不适用于简单场景
    在简单的场景下,使用访者模式可能会引入不必要的复杂性

相关文章:

设计模式二十四:访问者模式(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 ----- 套接字的选项

一、优雅的断开套接字连接 之前套接字的断开都是单方面的。 &#xff08;一&#xff09;基于TCP的半关闭 Linux的close函数和windows的closesocket函数意味着完全断开连接。完全断开不仅不能发送数据&#xff0c;从而也不能接收数据。在某些情况下&#xff0c;通信双方的某一方…...

区块链金融项目怎么做?

区块链技术的兴起引发了金融领域的变革&#xff0c;为金融行业带来了前所未有的机遇与挑战。在这个快速发展的领域中&#xff0c;如何在区块链金融领域做出卓越的表现&#xff1f;本文将从专业性和思考深度两个方面&#xff0c;探讨区块链金融的发展路径&#xff0c;并为读者提…...

Redis与数据库保持一致

参考链接 先更新数据库&#xff0c;再更新redis 存在漏洞&#xff0c;如果更新Redis失败&#xff0c;仍然会导致不一致 先删Redis&#xff0c;再更新数据库并同步数据到Redis 存在漏洞&#xff0c;多线程情况下,线程1删除redis后&#xff0c;还是有可能被其他线程读取旧的数据…...

idea中vue项目 npm安装插件后node modules中找不到

从硬盘中重新加载一下...

已知两地经纬度,计算两地直线距离

文章目录 1 原理公式2 代码实现2.1 JavaScript2.2 C2.3 Python2.4 MATLAB 1 原理公式 在地球上&#xff0c;计算两点之间的直线距离通常使用地理坐标系&#xff08;例如WGS84&#xff09;。计算两地直线距离的公式是根据经纬度之间的大圆距离&#xff08;Great Circle Distanc…...

我想开通期权?如何开通期权账户?

场内期权的合约由交易所统一标准化定制&#xff0c;大家面对的同一个合约对应的价格都是一致的&#xff0c;比较公开透明&#xff0c;期权开户当天不能交易的&#xff0c;期权开户需要满足20日日均50万及半年交易经验即可操作&#xff0c;下文科普我想开通期权&#xff1f;如何…...

ChatGPT对软件测试的影响

ChatGPT 是一个经过预训练的 AI 语言模型&#xff0c;可以通过聊天的方式回答问题&#xff0c;或者与人闲聊。它能处理的是文本类的信息&#xff0c;输出也只能是文字。它从我们输入的信息中获取上下文&#xff0c;结合它被训练的大模型&#xff0c;进行分析总结&#xff0c;给…...

minion在ubuntu上的搭建步骤

在Ubuntu上搭建MinIO可以按照以下步骤进行&#xff1a; 下载MinIO服务器二进制文件&#xff1a; 通过浏览器访问 https://min.io/download 或使用以下命令获取最新的MinIO二进制文件&#xff1a;wget https://dl.min.io/server/minio/release/linux-amd64/minio赋予二进制文件…...

Leetcode刷题笔记--Hot31-40

1--颜色分类&#xff08;75&#xff09; 主要思路&#xff1a; 快排 #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版本安装

总结&#xff1a; 使用conda新建切换环境&#xff0c;然后使用pip安装卸载包 【python】pip conda_conda list没有pytorch_myaijarvis的博客-CSDN博客 pip换源 https://blog.csdn.net/maotenghua/article/details/104188086 在当前用户目录下创建pip目录&#xff0c;即C:\U…...

BEVFusion复现 (Ubuntu RTX3090)

https://github.com/ADLab-AutoDrive/BEVFusion 1.环境安装 我的机器是RTX3090&#xff0c;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基本语法 标识符 标识符由数字、字符串、下划线构成。 注意事项&#xff1a; 标识符不以数字开头区分大小写下划线开头的标识符具有特殊意义保留字&#xff0c;Python保留了一些关键字&#xff0c;这些关键字都是通过小写字母进行保存。 下划线开头的特…...

SpringBoot笔记——(狂神说)——待续

路线 javase: OOPmysql:持久化 htmlcssjsjquery框架:视图&#xff0c;框架不熟练&#xff0c;css不好; javaweb:独立开发MVC三层架构的网站了∶原始 ssm :框架:简化了我们的开发流程&#xff0c;配置也开始较为复杂; war: tomcat运行 spring再简化: SpringBoot - jar:内嵌tomca…...

Linux TCP编程流程

一、TCP编程流程 TCP 提供的是面向连接的、可靠的、字节流服务。TCP的服务器端和客户端编程流程如下&#xff1a; 1.socket()方法 用来创建一个套接字&#xff0c;有了套接字就可以通过网络进行数据的收发。这也是为什么进行网络通信的程序首先要创建一个套接字。创建套接字时…...

pyqt5 QuickStart

在使用pyqt5之前&#xff0c;建议下载一个Anaconda环境&#xff0c;这样下载python包更方便&#xff0c;本篇文章是建立在已经安装好Anaconda的情况下使用的。IDE就是标准的PyCharm了。 一、pyqt包的安装 python终端执行下面两个安装命令&#xff1a; pip install PyQt5 pip …...

Qt6 for Windows 环境搭建(Visual Studio)

作者&#xff1a; 一去、二三里 个人微信号&#xff1a; iwaleon 微信公众号&#xff1a; 高效程序员 在 Windows 中&#xff0c;如果想要开发 Qt 应用程序&#xff0c;可以选择多种方式&#xff1a; Qt Creator MinGW 编译器Qt Creator MSVC 编译器Visual Studio&#xff0…...

探索未知世界:桌面端3D GIS引领地理信息新时代

近年来&#xff0c;桌面端的三维地理信息系统&#xff08;3D GIS&#xff09;在地理信息领域迎来了显著的发展&#xff0c;为我们带来了更深入、更丰富的地理空间认知和数据分析体验。从城市规划到环境保护&#xff0c;从资源管理到应急响应&#xff0c;桌面端的3D GIS正逐渐成…...

微信小程序 趣味学习与益智游戏系统APP

管理员、用户可通过HBuilder系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、用户管理、学生分类管理、学一学管理、玩一玩管理、听一听管理、试题管理、练一练管理、系统管理、考试管理&#xff0c;用户前端&#xff1b;首页、学一学、玩…...

【单片机】UART、I2C、SPI、TTL、RS232、RS422、RS485、CAN、USB、SD卡、1-WIRE、Ethernet等常见通信方式

在单片机开发中&#xff0c;UART、I2C、RS485等普遍在用&#xff0c;这里做一个简单的介绍 UART通用异步收发器 UART口指的是一种物理接口形式(硬件)。 UART是异步&#xff08;指不使用时钟同步&#xff0c;依靠帧长进行判断&#xff09;&#xff0c;全双工&#xff08;收发…...

【Java从0到1学习】13 Java IO流

1. 流 1.1 流的概念 流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中&#xff0c;管道是一条不间断的字节流&#xff0c;用来实现程序或进程间的通信&#xff0c;或读写外围设备、外部文件等。 一个流&#xff0c;必有源端和目的端&#xff0c;它们可以是计算机内存的…...

linux并发服务器 —— 多进程并发(四)

进程概述 程序是包含一系列信息的文件&#xff0c;描述了如何在运行时创建一个进程&#xff1b; 进程是正在运行的程序的实例&#xff0c;可以用一个程序来创建多个进程&#xff1b; 用户内存空间包含程序代码以及代码所使用的变量&#xff0c;内核数据结构用于维护进程状态…...

华为云Stack的学习(四)

五、Service OM资源管理 1.Service OM简介 1.1 Service OM介绍 在华为云Stack解决方案中&#xff0c;Service OM是FusionSphere OpenStack的操作管理界面&#xff0c;是资源池&#xff08;计算、存储、网络&#xff09;以及基础云服务的管理工具。 1.2 Service OM定位 Serv…...

Midjourney 完整版教程(从账号注册到设计应用)

目录 一、Midjourney 介绍 二、Midjourney 的AI出图示例 三、手把手教你上手Midjourney 1、账号&初始化 1.1 账号注册登录 1.2 账号付费 1.3 账号初始化 2、Midjourney的基础设置 3、Midjourney 出图步骤。 (一)直接描述出图 (二)垫图生图。 4、Midjourney的…...

保护香港服务器的方法

保护香港服务器的方法 当你把一个香港服务器完全留给一个组织、应用程序或个人使用时&#xff0c;它被称为香港服务器租用。在这种类型的主机配置中&#xff0c;客户端将会借出整个服务器&#xff0c;并且不允许其他任何人使用它。 如果您计划使用香港服务器&#xff0c;安全性…...

Redis——》Pipeline

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…...