设计模式(十四)行为型模式---访问者模式(visitor)
文章目录
- 访问者模式简介
- 分派的分类
- 什么是双分派?
- 结构
- UML图
- 具体实现
- UML图
- 代码实现
- 优缺点
访问者模式简介
- 访问者模式(visitor pattern)是封装一些作用于某种数据结构中的元素的操作,它可以在不改变这个数据结构(实现例子中的、男女)的前提下,定义作用于这些原则新的操作(实现例子中的成功、失败、待定等结果)。
分派的分类
- 静态分派:就是程序编译的时候,根据参数类型就可以确定的分派。
- 动态分派:因为参数是父类或者接口,具体由谁执行需要根据接口传入参数具体类型确定的分派。
什么是双分派?
- 双分派:就是经历两次上面的分派过程就是双分派。
结构
- 1.抽象访问者角色(Visitor):定义了对每一个原色(Element)访问的行为,他的参数就是可以访问的元素,他的方法个数理论上和元素个数是一致的,所以访问者模式要求元素类的个数不能改变。
- 2.具体访问者角色(Concrete Visitor):给出对每一个元素访问时所产生的具体行为(demo中的成功、失败、待定)
- 3.抽象元素角色(Element):定义了一个接受访问者的方法(accept),其意思就是每一个元素都可以被访问者访问。
- 4.具体元素就角色(Concrete Element):提供了接受访问方法的具体实现,这个具体实现,通常情况下是使用访问者提供的访问该元素的方法。
- 5.对象结构角色(Object Structure):可以理解为具体元素的存储容器。
UML图

具体实现
例子:好声音,对男女选手进行评审。
UML图

代码实现
- 抽象元素角色
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 抽象元素角色 提供一个方法让访问者可以访问* @date 2024/5/26 0:18*/
public abstract class Person {/*** @description 提供给访问者访问的防方法,访问者通过参数传递进来。* @author xxliao* @date 2024/5/26 0:28*/public abstract void result(ActionVisitor actionVisitor);
}
- 具体元素角色
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 具体元素角色,接受一个访问者方法* @date 2024/5/26 0:18*/
public class Man extends Person{/*** @description 具体元素角色提供给访问者的防方法,访问者通过参数传递进来* @author xxliao* @date 2024/5/26 0:29*/@Overridepublic void result(ActionVisitor actionVisitor) {// 访问者对象 获取 本元素(man)对象的结果,将本对象自己传递进去,这里使用了双分派actionVisitor.getManResult(this);}
}
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 具体元素角色* @date 2024/5/26 0:19*/
public class Woman extends Person{/*** @description 具体元素角色提供给访问者的防方法,访问者通过参数传递进来* @author xxliao* @date 2024/5/26 0:29*/@Overridepublic void result(ActionVisitor actionVisitor) {// 访问者对象 获取 本元素(woman)对象的结果,将本对象自己传递进去,这里使用了双分派actionVisitor.getWomanResult(this);}
}
- 抽象访问者角色
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 抽象访问者角色,角色内定义访问方法,一般来说要包括所有的具体抽象元素* @date 2024/5/26 0:18*/
public abstract class ActionVisitor {/*** @description Man get result* @author xxliao* @date 2024/5/26 0:20*/public abstract void getManResult(Man man);/*** @description Woman get result* @author xxliao* @date 2024/5/26 0:20*/public abstract void getWomanResult(Woman woman);
}
- 具体访问者角色
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 具体访问者角色 -成功* @date 2024/5/26 0:22*/
public class SuccessActionVisitor extends ActionVisitor{@Overridepublic void getManResult(Man man) {System.out.println("man --- success");}@Overridepublic void getWomanResult(Woman woman) {System.out.println("woman --- success");}
}
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 具体访问者角色 -失败* @date 2024/5/26 0:22*/
public class FailActionVisitor extends ActionVisitor{@Overridepublic void getManResult(Man man) {System.out.println("man --- fail");}@Overridepublic void getWomanResult(Woman woman) {System.out.println("woman --- fail");}
}
- 对象结构角色
package com.xxliao.pattern.behavioral.visitor.demo;import java.util.LinkedList;
import java.util.List;/*** @author xxliao* @description: 对象结构,需要定义存储具体元素角色的容器,然后* @date 2024/5/26 0:24*/
public class ObjectStructure {// 定义存储具体元素对象的容器private List<Person> persons = new LinkedList<>();// 添加具体元素对象public void addPerson(Person person) {persons.add(person);}// 移除具体元素对象public void removePerson(Person person) {persons.remove(person);}/*** @description 显示最后结果* @author xxliao* @date 2024/5/26 0:35*/public void print(ActionVisitor actionVisitor){for (Person person : persons) {person.result(actionVisitor);}}
}
- 测试客户端
package com.xxliao.pattern.behavioral.visitor.demo;/*** @author xxliao* @description: 访问者模式 测似客户端* @date 2024/5/26 0:36*/
public class Client {public static void main(String[] args) {// 创建 对象结构ObjectStructure objectStructure = new ObjectStructure();// 添加具体元素对象objectStructure.addPerson(new Man());objectStructure.addPerson(new Woman());// 创建访问者具体对象 --成功SuccessActionVisitor successActionVisitor = new SuccessActionVisitor();// 对象结构 显示最后结果objectStructure.print(successActionVisitor);}
}
- 测试结果

优缺点
- 优点:.在元素个数不变的情况下,增加新功能(具体访问者对象),做到了开闭原则。
- 缺点:在元素个数要变化的情况下,所有的具体访问者对象都要修改代码, 不符合开闭原则。
相关文章:
设计模式(十四)行为型模式---访问者模式(visitor)
文章目录 访问者模式简介分派的分类什么是双分派?结构UML图具体实现UML图代码实现 优缺点 访问者模式简介 访问者模式(visitor pattern)是封装一些作用于某种数据结构中的元素的操作,它可以在不改变这个数据结构(实现…...
【Matplotlib作图-3.Ranking】50 Matplotlib Visualizations, Python实现,源码可复现
目录 03 Ranking 3.0 Prerequisite 3.1 有序条形图(Ordered Bar Chart) 3.2 棒棒糖图(Lollipop Chart) 3.3 点图(Dot Plot) 3.4 斜率图(Slope Chart) 3.5 杠铃图(Dumbbell Plot) References 03 Ranking 3.0 Prerequisite Setup.py # !pip install brewer2mpl import n…...
加入不正确的位置编码会破坏掉原本的信息吗?
会 位置编码的作用 在Transformer中,位置编码的主要作用是让模型感知输入序列中各个词的位置。因为Transformer完全依赖自注意力机制,它本身并没有序列信息,位置编码的引入就是为了补充这一点。 加法操作的合理性 位置编码通过加法操作与…...
区块链合约开发流程
区块链合约开发,尤其是以太坊智能合约开发,是一个多步骤的过程,从需求分析到部署和维护,每一步都需要仔细规划和执行。以下是详细的开发流程。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合…...
建筑企业有闲置资质怎么办?
如果建筑企业拥有闲置资质,可以考虑以下几种方式来充分利用这些资质: 1. 租赁或转让资质: 将闲置的建筑资质租赁给其他企业或个人使用,或者通过转让的方式将资质出售给有需要的企业或个人。 2. 提供咨询服务: 利用建…...
Java开发-特殊文本文件,日志技术
目录 01.特殊文件,日志技术概述 02.特殊文件:Properties属性文件 编辑Properties案例 特殊文件:XML文件 XML的作用和应用场景 读取XML文件中的数据 XML的生成 约束XML文件的编写[了解] 日志技术 日志技术的体系 编辑 编辑 Logback日志框架的概述 Logback快…...
Django ORM深度游:探索多对一、一对一与多对多数据关系的奥秘与实践
系列文章目录 Django入门全攻略:从零搭建你的第一个Web项目Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解Django ORM深度游ÿ…...
无人机路径规划:基于鸽群优化算法PIO的无人机三维路径规划MATLAB代码
一、无人机模型介绍 无人机三维航迹规划_无人机航迹规划-CSDN博客 二、部分代码 close all clear clc warning (off) global model global gca1 gca2 gca3 gca4 model CreateModel(); % Create search map and parameters load(BestPosition5.mat); load(ConvergenceCurve5…...
ArcGIS属性域和子类型
01 属性域 道路的车道数值是小于10的。在编辑道路的此属性时,为了限制其值在10以内,可以使用属性域。当输入数据超过10时,就会限制输入。 限制输入这个功能是Pro特有的,在ArcMap中输入超出限制的值也是合法的,需要手动…...
电子电器架构 --- 什么是域控制器?
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...
链表头部插入结点
Linked List Inserting a node at beginning #include<stdlib.h>//为了用malloc #include<stdio.h> struct node {int data;struct node* next;//在cpp中可以只写 Node *Link;//为了表意明确,Link也经常被命名为next }; struct node* head…...
k8s集群修改apiserver的ip地址
有时候由于服务器的调整,导致ip的的变化,k8s集群的api大管家的ip变动会导致kubectl的接口都无法正常使用,这是只需要将k8s主节点配置文件的ip替换即可。 例如无需要将原来的192.168.146.202的ip替换成192.168.85.202,执行一下操作…...
C语言编程技巧:深度挖掘与高效实践
C语言编程技巧:深度挖掘与高效实践 在编程的世界里,C语言以其高效、灵活和底层控制能力强等特点,一直备受开发者们的青睐。然而,要想真正掌握C语言的精髓,并编写出高效、健壮的代码,却并非易事。本文将从四…...
十_信号14 - system()
意思是 应在在调用 system() 函数前 阻塞 SIGCHLD 信号,否则,子进程结束的时候,系统会向该进程(父)发送 SIGCHLD信号,则该进程认为是自己的一个子进程结束了,于是调用 wait函数获取子进程的终止状态。这本来是正常的操…...
【Python网络爬虫】详解python爬虫中URL资源抓取
🔗 运行环境:PYTHON 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 #### 防伪水印——左手の明天 #### 💗 大家好🤗ᾑ…...
AI办公自动化:用kimi批量提取音频中的标题并重命名
很多音频文件,文件名很乱,需要根据音频信息中的标题聪明吗 在kimi中输入提示词: 你是一个Python编程专家,一步步的思考,完成以下脚本的撰写: 打开文件夹:E:\有声\a16z播客 读取里面所有的mp3格…...
flyfish3.0.0配置避坑
1.基础环境准备篇 doc/01-基础环境准备篇.md 云智慧/FlyFish - Gitee.com 使用教程里给出的java环境时,可以显示java版本,但是不能显示Maven的版本 改为: export NODE_HOME/usr/local/node/node-v14.19.3-linux-x64 export PATH$NODE_HOME…...
Spring (33)CSRF(跨站请求伪造)保护
跨站请求伪造(CSRF)是一种常见的网络攻击手段,它允许攻击者在不知情的用户浏览器中发起恶意请求。这种攻击利用了网站对用户浏览器的信任。如果用户在浏览器中已经登录了一个网站,攻击者就可以构造一个请求,这个请求能…...
【一刷《剑指Offer》】面试题 29:数组中出现次数超过一半的数字
力扣对应题目链接:169. 多数元素 - 力扣(LeetCode) 牛客对应题目链接:数组中出现次数超过一半的数字_牛客题霸_牛客网 (nowcoder.com) 核心考点 : 数组使用,简单算法的设计。 一、《剑指Offer》对应内容 二…...
vx小程序初学
小程序初学 在我还没接触到微信小程序之前,通常使用轮播要么手写或使用swiper插件去实现,当我接触到微信小程序之后,我看到了微信小程序的强大之处,让我为大家介绍一下吧! swiper与swiper-item一起使用可以做轮播图 …...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
WEB3全栈开发——面试专业技能点P7前端与链上集成
一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染(SSR)与静态网站生成(SSG) 框架,由 Vercel 开发。它简化了构建生产级 React 应用的过程,并内置了很多特性: ✅ 文件系…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
