访问者模式(Visitor)

访问者模式是一种行为设计模式,可封装一些作用于当前数据结构的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

Visitor is a behavior design pattern that encapsulates some operations that act on the elements of the current 
data structure. It can define new operations that act on these elements without changing the data structure.  

结构设计

访问者模式包含如下角色:
Visitor,访问者基类,声明了一系列以对象结构的具体元素为参数的访问者方法。这些方法的名称可能是相同的,但是其参数一定是不同的。
ConcreteVisitor,具体访问者,会为不同的具体元素类实现相同行为的几个不同版本。
ObjectStructure,对象结构类,该类能枚举它包含的元素,可以提供一个高层的接口以允许访问者访问它的元素。
Element,元素,声明了一个方法来“接收”(accept)访问者。该方法必须有一个参数被声明为访问者接口类型。
ConcreteElement,具体元素,实现Element声明的接口。该方法的目的是根据当前元素类将其调用重定向到相应访问者的方法。
Client,客户端,客户端通常不知晓所有的具体元素类,因为它们会通过抽象接口与集合中的对象进行交互。
访问者模式类图表示如下:
请添加图片描述
访问者模式可将数据结构与数据操作分离,可以解决稳定的数据结构和易变的操作耦合问题。

伪代码实现

接下来将使用代码介绍下访问者模式的实现。

// 1、访问者基类,声明了对对象结构的具体元素为参数的访问者方法
public interface IVisitor {void visitElement(ConcreteElementA element);void visitElement(ConcreteElementB element);
}//2、具体访问者,为不同的具体元素类实现相同行为的几个不同版本
public class ConcreteVisitorA implements IVisitor {@Overridepublic void visitElement(ConcreteElementA element) {System.out.println("handle a ConcreteElementA instance in ConcreteVisitorA");}@Overridepublic  void visitElement(ConcreteElementB element) {System.out.println("handle a ConcreteElementB instance in ConcreteVisitorA");}
}
public class ConcreteVisitorB implements IVisitor {@Overridepublic void visitElement(ConcreteElementA element) {System.out.println("handle a ConcreteElementA instance in ConcreteVisitorB");}@Overridepublic  void visitElement(ConcreteElementB element) {System.out.println("handle a ConcreteElementB instance in ConcreteVisitorB");}
}// 3、元素,声明了一个方法来“接收”(accept)访问者。该方法必须有一个参数被声明为访问者接口类型
public interface IElement {void accept(IVisitor visitor);
}// 4、具体元素,实现Element声明的接口
public class ConcreteElementA implements IElement {public void accept(IVisitor visitor) {visitor.visitElement(this);}
}
public class ConcreteElementB implements IElement {public void accept(IVisitor visitor) {visitor.visitElement(this);}
}// 5、对象结构类,可枚举它包含的元素,可以提供一个高层的接口以允许访问者访问它的元素
public class ObjectStructure {private IElement elementA;private IElement elementB;public ObjectStructure(IElement elementA, IElement elementB) {this.elementA = elementA;this.elementB = elementB;}public IElement getElementA() {return this.elementA;}public IElement getElementB() {return this.elementB;}
}// 6、客户端
public class VisitorClient {public void test() {// (1) 创建元素实例IElement elementA = new ConcreteElementA();IElement elementB = new ConcreteElementB();// (2) 创建对象结构实例ObjectStructure objectStructure = new ObjectStructure(elementA, elementB);// (3) 创建具体访问者实例IVisitor visitorA = new ConcreteVisitorA();// (4) 调用访问者方法visitorA.visitElement((ConcreteElementA) objectStructure.getElementA());visitorA.visitElement((ConcreteElementB) objectStructure.getElementB());IVisitor visitorB = new ConcreteVisitorB();visitorB.visitElement((ConcreteElementA) objectStructure.getElementA());visitorB.visitElement((ConcreteElementB) objectStructure.getElementB());}
}

适用场景

在以下情况下可以考虑使用访问者模式:
(1) 如果需要对一个复杂对象结构中的所有元素执行某些操作,可考虑使用访问者模式。访问者模式通过在访问者对象中为多个目标类提供相同操作的变体,
让开发者能在属于不同类的一组对象上执行同一操作。
(2) 可使用访问者模式来清理辅助行为的业务逻辑。访问者模式可将所有非主要的行为抽取到一组访问者类中,使得程序的主要类能更专注于主要的工作。
(3) 当某个行为仅在类层次结构中的一些类中有意义,而在其他类中没有意义时,可考虑使用访问者模式。可将该行为抽取到单独的访问者类中,
只需实现接收相关类的对象作为参数的访问者方法并将其他方法留空即可。

优缺点

访问者模式有以下优点:
(1) 符合开闭原则。以引入在不同类对象上执行的新行为, 且无需对这些类做出修改。
(2) 符合单一职责原则。可将同一行为的不同版本移到同一个类中。
但是该模式也存在以下缺点:
(1) 代码可能会变得更加复杂。使用访问者模式可能会导致某些系统有过多的具体访问者类。
(2) 每次在元素层次结构中添加或移除一个类时,都要更新所有的访问者,所以该模式对于频繁调整对象结构的类并不友好。
(3) 在访问者同某个元素进行交互时,可能没有访问元素私有成员变量和方法的必要权限。这与迪米特法则相违背。
(4) 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素。

参考

《设计模式 可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英军, 马晓星等译
https://refactoringguru.cn/design-patterns/visitor 访问者模式
https://www.runoob.com/design-pattern/visitor-pattern.html 访问者模式
https://www.cnblogs.com/adamjwh/p/10968634.html 简说设计模式——访问者模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/28799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

积累常见的有针对性的python面试题---python面试题001

1.考点列表的.remove方法的参数是传入的对应的元素的值,而不是下标 然后再看remove这里,注意这个是,删除写的那个值,比如这里写3,就是删除3, 而不是下标. remove不是下标删除,而是内容删除. 2.元组操作,元组不支持修改,某个下标的内容 可以问他如何修改元组的某个元素 3.…

Vue3 第五节 一些组合式API和其他改变

1.provide和inject 2.响应式数据判断 3.Composition API的优势 4.新的组件 5.其他改变 一.provide和inject 作用:实现祖与后代组件间通信 套路:父组件有一个provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据 &…

AcWing算法提高课-1.3.17背包问题求具体方案

宣传一下算法提高课整理 <— CSDN个人主页&#xff1a;更好的阅读体验 <— 本题链接&#xff08;AcWing&#xff09; 点这里 题目描述 有 N N N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。 第 i i i 件物品的体积是 v i v_i vi​&#xff0c;价值…

HEIF—— 1、vs2017编译Nokia - heif源码

HEIF(高效图像文件格式) 一种图片有损压缩格式,它的后缀名通常为".heic"或".heif"。 HEIF 是由运动图像专家组 (MPEG) 标准化的视觉媒体容器格式,用于存储和共享图像和图像序列。它基于著名的 ISO 基本媒体文件格式 (ISOBMFF) 标准。HEIF读写器引擎…

【C++】位图|布隆过滤器|海量数据处理面试题

文章目录 一.位图1. 位图的概念2. 位图的使用3. 位图的实现 二.布隆过滤器1. 布隆过滤器2. 布隆过滤器的实现 三.海量数据处理面试题1.位图2.布隆过滤器3.哈希切割 一.位图 1. 位图的概念 所谓位图&#xff0c;就是用每一位来存放某种状态&#xff0c;适用于海量数据&#xf…

【LeetCode】删除并获得点数

删除并获得点数 题目描述算法分析编程代码空间优化 链接: 删除并获得点数 题目描述 算法分析 编程代码 class Solution { public:int deleteAndEarn(vector<int>& nums) {const int N 10001;int arr[N] {0};for(const auto& n : nums){arr[n]n;}vector<in…

2.安装Docker-ce

一、删除之前安装的docker(若之前未安装过&#xff0c;此步骤省略…) 进入centos根目录执行以下命令&#xff08;\ 是linux系统种命令换行符&#xff0c;如果命令过长&#xff0c;可以用\来换行&#xff09; yum remove docker \ docker-client \ docker-client-latest \ doc…

尚品汇总结十:秒杀模块(面试专用)

1、需求分析 所谓“秒杀”&#xff0c;就是商家发布一些超低价格的商品&#xff0c;所有买家在同一时间网上抢购的一种销售方式。通俗一点讲就是商家为促销等目的组织的网上限时抢购活动。由于商品价格低廉&#xff0c;往往一上架就被抢购一空&#xff0c;有时只用一秒钟。 秒…

状态模式(State)

状态模式是一种行为设计模式&#xff0c;允许一个对象在其内部状态改变时改变它的行为&#xff0c;使其看起来修改了自身所属的类。其别名为状态对象(Objects for States)。 State is a behavior design pattern that allows an object to change its behavior when its inter…

谷歌广告(Google ads)如何投放?新手必看的超全教程

Google是公认的全球最大的搜索引擎&#xff0c;同时&#xff0c;Google还通过旗下的 YouTube、Gmail、Google Play、Android等产品&#xff0c;汇集了海量的海外用户。对于跨境出海商家来说&#xff0c;谷歌广告是提高销售额、提高产品流量、拓展全球市场的重要推广渠道。 那么…

一文走进时序数据库性能测试工具 TSBS

一、背景 在物联网、车联网等时序数据场景中&#xff0c;数据的高速写入能力至关重要&#xff0c;会对产品方案的可用性、可靠性和扩展性产生影响。 以物联网为例&#xff0c;当面临千万甚至上亿设备、平均每个设备采集几十个到几百个指标时&#xff0c;每秒生成的数据将达到…

Docker+Consul+Registrator 实现服务注册与发现

第四阶段 时 间&#xff1a;2023年8月8日 参加人&#xff1a;全班人员 内 容&#xff1a; DockerConsulRegistrator 实现服务注册与发现 目录 一、服务注册中心引言 CAP理论是分布式架构中重要理论&#xff1a; 二、服务注册中心软件 &#xff08;一&#xff09;Zoo…

ELK 将数据流转换回常规索引

ELK 将数据流转换回常规索引 现象&#xff1a;创建索引模板是打开了数据流&#xff0c;导致不能创建常规索引&#xff0c;并且手动修改、删除索引模板失败 "reason" : "composable template [logs_template] with index patterns [new-pattern*], priority [2…

MQTT 订阅接收消息 mosquitto 方式

1 说明 采用 mosquitto 库&#xff0c;实现订阅主题&#xff0c;并接收消息。其中服务器有做限制&#xff0c;需要对应的 cilent id &#xff0c;cafile 、certfile 、keyfile 等配置2 环境 采用ubuntu 直接编译调试 安装mosquitto 库 sudo apt install libmosquitto-dev su…

chatGLM 本地部署(windows+linux)

chatGLM算是个相对友好的模型&#xff0c;支持中英文双语的对话交流&#xff0c;清华出的 我的教程无需特别的网络设置&#xff0c;不过部分情况因为国内网络速度慢&#xff0c;需要反复重复 chatGLM github地址 一、硬件需求 N卡8G显存以上&#xff0c;最好16G以上&#xff…

SuperMap GIS基础产品桌面GIS FAQ集锦(5)

SuperMap GIS基础产品桌面GIS FAQ集锦&#xff08;5&#xff09; 【iDesktop】【iDesktopX】态势推演怎么使用&#xff1f; 【解决办法】 1、要先新建一个CAD数据集&#xff0c;然后将标绘加到CAD数据集中。 2、再使用态势推演管理器&#xff0c;右键新建分组。 3、选中场景中的…

【算法|数组】手撕经典二分法

算法|数组——二分查找 文章目录 算法|数组——二分查找引言二分查找左闭右闭写法左闭右开写法 总结 引言 首先学习这个算法之前需要了解数组知识&#xff1a;数组。 大概介绍以下&#xff1a; 数组是存储在连续内存空间上的相同类型数据的集合。数组下标都是从0开始。数组在…

数学建模—多元线性回归分析(+lasso回归的操作)

第一部分&#xff1a;回归分析的介绍 定义&#xff1a;回归分析是数据分析中最基础也是最重要的分析工具&#xff0c;绝大多数的数据分析问题&#xff0c;都可以使用回归的思想来解决。回归分析的人数就是&#xff0c;通过研究自变量X和因变量Y的相关关系&#xff0c;尝试去解释…

webshell链接工具-Godzilla(哥斯拉)

项目地址 https://github.com/BeichenDream/Godzilla

势不可挡!新能源车型L2搭载率破50%,TOP20品牌数据出炉

中国乘用车市场正在走出去年的阴霾。 机构公开数据显示&#xff0c;2023年上半年中国乘用车市场产量1100.77万辆&#xff0c;同比增长7.5%&#xff1b;终端销量959.08万辆&#xff0c;同比增长4.7%&#xff1b;乘用车出口152.36万辆&#xff0c;同比增长87.6%。 在实际交付量…