软件设计模式与体系结构-设计模式-行为型软件设计模式-访问者模式
目录
- 二、访问者模式
- 概念
- 代码
- 类图
- 实例一:名牌运动鞋专卖店销售软件
- 实例二:计算机部件销售软
- 优缺点
- 适用场合
- 课程作业
二、访问者模式
概念
- 对于系统中的某些对象,它们存储在同一个集合中,具有不同的类型
- 对于该集合中的对象,可以接受一类被称为访问者的对象来访问
- 不同的访问者其访问方式有所不同
目的:
封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变
模式动机:
为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式
缺点:将所有的税率运算分布到不同的结点类使得系统不容易理解、维护与改变。
如果要增加一个新的功能,则要在很多结点类都写入新的代码,且要重新编译所有的类。
当税率变化时要修改每个结点上的calculateTax()代码。
因此,该设计的可扩展性和可维护性都不好。
解决方案:分离“Tax”类及其“calculateTax()”功能。
将所有结点的税额计算方法都从原来的类中分离出来,放入另外一个独立的类,叫做“TaxCalculation”类,设计图如下。
设计思想:将原来分布于各结点中的计算税额的方法都放在一个TaxCalculation类中。当要计算某个结点的税额时,则调用TaxCalculation中某个相应的方法进行计算。
代码
访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不改变被访问对象的结构的情况下,定义对其元素的新操作。访问者模式将数据结构和对数据的操作分离开来,使得操作可以独立变化而不影响数据结构。
在访问者模式中,有以下几个角色:
-
访问者(Visitor):定义了对不同元素的访问操作,每个具体访问者都实现了对应的访问方法,用于处理特定类型的元素。
-
具体访问者(Concrete Visitor):实现了访问者定义的访问方法,具体处理不同类型元素的操作。
-
元素(Element):定义了接受访问者访问的接口,可以是抽象类或接口。
-
具体元素(Concrete Element):实现了元素定义的接口,具体元素可以有不同的类型,每个具体元素都可以接受访问者的访问。
-
对象结构(Object Structure):包含元素的集合,可以是一个容器,也可以是一个复杂的数据结构。
下面是一个简单的访问者模式的示例代码,以展示其使用方式和实现原理:
// 定义元素接口
interface Element {void accept(Visitor visitor);
}// 具体元素A
class ConcreteElementA implements Element {public void accept(Visitor visitor) {visitor.visitConcreteElementA(this);}public String operationA() {return "具体元素A的操作";}
}// 具体元素B
class ConcreteElementB implements Element {public void accept(Visitor visitor) {visitor.visitConcreteElementB(this);}public String operationB() {return "具体元素B的操作";}
}// 定义访问者接口
interface Visitor {void visitConcreteElementA(ConcreteElementA element);void visitConcreteElementB(ConcreteElementB element);
}// 具体访问者
class ConcreteVisitor implements Visitor {public void visitConcreteElementA(ConcreteElementA element) {System.out.println("访问者对" + element.operationA() + "的操作");}public void visitConcreteElementB(ConcreteElementB element) {System.out.println("访问者对" + element.operationB() + "的操作");}
}// 对象结构
class ObjectStructure {private List<Element> elements = new ArrayList<>();public void addElement(Element element) {elements.add(element);}public void removeElement(Element element) {elements.remove(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 示例代码的使用
public class VisitorPatternExample {public static void main(String[] args) {// 创建对象结构ObjectStructure objectStructure = new ObjectStructure();// 添加具体元素A和BobjectStructure.addElement(new ConcreteElementA());objectStructure.addElement(new ConcreteElementB());// 创建具体访问者Visitor visitor = new ConcreteVisitor();// 对对象结构中的元素进行访问操作objectStructure.accept(visitor);}
}
在上述示例代码中,访问者模式的核心在于访问者(Visitor)和元素(Element)的交互。具体的访问者定义了访问不同元素的方法,而具体元素实现了接受访问者访问的接口。通过对象结构将元素组织起来,并调用访问者的访问方法,实现对元素的访问操作。
访问者模式的优点包括:
- 将数据结构和操作解耦,使得新增访问操作变得容易。
- 可以对元素的操作进行扩展,而不需要修改元素的结构。
- 符合开闭原则,增加新的访问者只需要新增具体访问者,而不需要修改其他代码。
然而,访问者模式也有一些限制和注意事项:
- 增加新的元素可能会导致访问者接口的修改,从而需要修改所有的具体访问者。
- 对象结构中的元素类型较多时,会导致具体访问者的访问方法过多,增加了维护的复杂性。
- 访问者模式适用于数据结构相对稳定,但经常需要新增操作的场景,对于数据结构变化频繁的场景,使用访问者模式可能不合适。
总而言之,访问者模式提供了一种灵活的方式来对数据结构的元素进行新的操作,同时也将访问逻辑与元素的结构解耦,使得系统更加灵活、可扩展和易于维护。
类图
访问者模式:表示一个作用于某对象结构中的个元素的操作,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
访问者模式是一种对象行为型模式
首先分为两个部分,一是元素类,而是访问者类
先抽象再具体
在访问者类里要有访问元素的方法visitXXX(抽象元素父类做参数)之类的
在元素类里要有接受访问的方法,比如accept(抽象访问者父类做参数)等
实例一:名牌运动鞋专卖店销售软件
在客户程序中将直接创建运动鞋子类与访问者子类的对象,然后直接调用运动鞋子类的 accept 方法。根据用户输入的所购买鞋的数量和单价来计算总价和获得相应特点的功能分别由 Visitor 类的两个子类 PriceVisitor 和 ShoeInfoVisitor 来实现。访问者类图如下。
实例二:计算机部件销售软
优缺点
优点:
- 使得增加新的访问操作变得很容易。
- 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散到一个个的元素类中。
- 可以跨过类的等级结构访问属于不同的等级结构的元素类。
- 让用户能够在不修改现有类层次结构的情况下,定义该类层次结构的操作。
缺点:
- 增加新的元素类很困难,违背了“开闭原则”的要求。
- 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。
适用场合
对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作
课程作业
相关文章:

软件设计模式与体系结构-设计模式-行为型软件设计模式-访问者模式
目录 二、访问者模式概念代码类图实例一:名牌运动鞋专卖店销售软件实例二:计算机部件销售软优缺点适用场合课程作业 二、访问者模式 概念 对于系统中的某些对象,它们存储在同一个集合中,具有不同的类型对于该集合中的对象&#…...

【LeetCode】503. 下一个更大元素 II
503. 下一个更大元素 II(中等) 方法:单调栈 「 对于找最近一个比当前值大/小」的问题,都可以使用单调栈来解决。栈可以很好的保存原始位置,最近影射栈顶。题目要求更大,因此更大即解–出栈,更小…...

使用infura创建以太坊网络
创建账号 https://www.infura.io/zh 进入控制台Dashboard,选择CREATE API KEY 创建成功后,进入API KEY查看,使用PostMan测试 返回result即为当前区块。...

TCP/IP协议是什么?
78. TCP/IP协议是什么? TCP/IP协议是一组用于互联网通信的网络协议,它定义了数据在网络中的传输方式和规则。作为前端工程师,了解TCP/IP协议对于理解网络通信原理和调试网络问题非常重要。本篇文章将介绍TCP/IP协议的概念、主要组成部分和工…...

python图像处理实战(三)—图像几何变换
🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?typeblog 🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初…...
学习vue2笔记
学习vue2笔记 文章目录 学习vue2笔记脚手架文件结构关于不同版本的Vuevue.config.js配置文件ref属性props配置项mixin(混入)插件scoped样式总结TodoList案例webStorage组件的自定义事件全局事件总线(GlobalEventBus)消息订阅与发布(pubsub&am…...

【SQL】查找多个表中相同的字段
--查找字段所在 SELECTbb.TABLE_NAME,bb.COLUMN_NAME ,aa.COLUMN_ID,aa.DATA_TYPE,aa.DATA_LENGTH ,bb.COMMENTS FROMuser_tab_cols aa JOIN user_col_comments bb ONaa.TABLE_NAME bb.TABLE_NAMEAND aa.COLUMN_NAME bb.COLUMN_NAME JOIN dba_objects cc ONbb.TABLE_NAME cc…...

“未来之光:揭秘创新科技下的挂灯魅力“
写在前面: 高度信息化当下时代,对电脑及数字设备的需求与日俱增无处不在,随之而来的视觉疲劳和眼睛问题也攀升到了前所未有的高度。传统台灯对于长时间使用电脑的人群来说是完全无法解决这些问题的。一款ScreenBar Halo 屏幕挂灯,…...
Spring boot MongoDB实现自增序列
在某些特定的业务场景下,会需要使用自增的序列来维护数据,目前项目中因为使用MongoDB,顾记录一下如何使用MongoDB实现自增序列。 MongoDB自增序列原理 MongoDB本身不具有自增序列的功能,但是MongoDB的$inc操作是具有原子性的&…...

MyBatis查询数据库【秘籍宝典】
0.MyBatis执行流程1.第一个MyBatis查询1.创建数据库和表1.2.添加MyBatis框架依赖【新项目】1.3.添加MyBatis框架依赖【旧项目】1.4.配置连接数据库1.5.配置MyBatis的XML路径2.MyBatis模式开发2.1 添加MyBatis的xml配置 3.增查改删(CRUD)5.1.增加操作5.2.…...

目标检测舰船数据集整合
PS:大家如果有想要的数据集可以私信我,如果我下载了的话,可以发给你们~ 一、光学数据集 1、 DIOR 数据集(已下载yolo版本)(论文中提到过) DIOR由23463张最优遥感图像和190288个目标实例组成,这些目标实例用…...

第一章 Android 基础--开发环境搭建
文章目录 1.Android 发展历程2.Android 开发机器配置要求3.Android Studio与SDK下载安装4.创建工程与创建模拟器5.观察App运行日志6.环境安装可能会遇到的问题7.练习题 本专栏主要在B站学习视频: B站Android视频链接 本视频范围:P1—P8 1.Android 发展历…...

【LeetCode周赛】2022上半年题目精选集——二分
文章目录 2141. 同时运行 N 台电脑的最长时间解法1——二分答案补充:求一个int数组的和,但数组和会超int 解法2——贪心解法 2251. 花期内花的数目解法1——二分答案代码1——朴素二分写法代码2——精简二分⭐ 解法2——差分⭐⭐⭐ 2258. 逃离火灾解法1—…...
vuejs如何将线上PDF转为base64编码
只需要两个方法-下载与转换: 下载方法: demoDownloadPDF(url) {// if (!(/^https?:/i.test(url))) return;if (window.XMLHttpRequest) var xhr new XMLHttpRequest(); else var xhr new ActiveXObject("MSXML2.XMLHTTP");xhr.open(GET, u…...
Repo工作原理及常用命令总结——2023.07
文章目录 1. 概要2. 工作原理2.1 项目清单库(.repo/manifests)2.2 repo脚本库(.repo/repo)2.3 仓库目录和工作目录2.4 repo 目录结构分析 3. 使用介绍3.1 init3.2 sync3.3 upload3.4 download3.5 forall3.6 prune3.7 start3.8 status 4. 使用实践4.1 对项目清单文件进行定制4.2…...

Python教程(2)——开发python常用的IDE
为什么需要IDE 在理解IDE之前,我们先做以下的实验,新建一个文件,输入以下代码 total_sum 0 for x in range(1,101):total_sum x print(total_sum)非常非常简单的一个程序,主要就是计算1加到100的值,我们将它重命名…...

【lambda函数】lambda()函数
lambda() lambda()语法捕捉列表mutable lambda 底层原理函数对象与lambda表达式 lambda()语法 lambda表达式书写格式: [capture-list] (parameters) mutable -> return-type{ statement }咱…...
ThreeJs CSS3DObject 点击失效问题
想实现一个在选中物体,弹出菜单,结果发现,点击会失效 <ul id"menu" class"list-group list-group-full"><li class"list-group-item" onclick"test()">24小时曲线</li><li cla…...

飞书深诺、恒生面试(部分)(未完全解析)
飞书深诺 说一下你对SaaS项目的理解?数据隔离是怎么处理的?Answer: 我们采用的是SAAS服务多租户数据隔离架构中的1.3共享数据库,通过租户ID来隔离,成本最低,隔离级别最低。Q:有没有开发隔离的中间件&#x…...

Spring Cloud Config: 了解、原理和使用
Spring Cloud Config: 了解、原理和使用 Spring Cloud Config 是 Spring Cloud 生态系统中的一个重要组件,它提供了一种分布式配置管理的解决方案,能够集中管理应用程序的配置,支持多种后端存储,如 Git、SVN、本地文件系统、Vaul…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...