软件设计模式与体系结构-设计模式-行为型软件设计模式-访问者模式

目录

  • 二、访问者模式
    • 概念
    • 代码
    • 类图
    • 实例一:名牌运动鞋专卖店销售软件
    • 实例二:计算机部件销售软
    • 优缺点
    • 适用场合
    • 课程作业

二、访问者模式

概念

  1. 对于系统中的某些对象,它们存储在同一个集合中,具有不同的类型
  2. 对于该集合中的对象,可以接受一类被称为访问者的对象来访问
  3. 不同的访问者其访问方式有所不同

目的:
封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变

模式动机:
为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式

在这里插入图片描述

缺点:将所有的税率运算分布到不同的结点类使得系统不容易理解、维护与改变。
如果要增加一个新的功能,则要在很多结点类都写入新的代码,且要重新编译所有的类。
当税率变化时要修改每个结点上的calculateTax()代码。
因此,该设计的可扩展性和可维护性都不好。

解决方案:分离“Tax”类及其“calculateTax()”功能。
将所有结点的税额计算方法都从原来的类中分离出来,放入另外一个独立的类,叫做“TaxCalculation”类,设计图如下。
设计思想:将原来分布于各结点中的计算税额的方法都放在一个TaxCalculation类中。当要计算某个结点的税额时,则调用TaxCalculation中某个相应的方法进行计算。
在这里插入图片描述

代码

访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不改变被访问对象的结构的情况下,定义对其元素的新操作。访问者模式将数据结构和对数据的操作分离开来,使得操作可以独立变化而不影响数据结构。

在访问者模式中,有以下几个角色:

  1. 访问者(Visitor):定义了对不同元素的访问操作,每个具体访问者都实现了对应的访问方法,用于处理特定类型的元素。

  2. 具体访问者(Concrete Visitor):实现了访问者定义的访问方法,具体处理不同类型元素的操作。

  3. 元素(Element):定义了接受访问者访问的接口,可以是抽象类或接口。

  4. 具体元素(Concrete Element):实现了元素定义的接口,具体元素可以有不同的类型,每个具体元素都可以接受访问者的访问。

  5. 对象结构(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 来实现。访问者类图如下。

实例二:计算机部件销售软

在这里插入图片描述
在这里插入图片描述

优缺点

优点:

  1. 使得增加新的访问操作变得很容易
  2. 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散到一个个的元素类中。
  3. 可以跨过类的等级结构访问属于不同的等级结构的元素类
  4. 让用户能够在不修改现有类层次结构的情况下,定义该类层次结构的操作

缺点:

  1. 增加新的元素类很困难,违背了“开闭原则”的要求
  2. 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

适用场合

对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作

课程作业

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Kafka request.log中RequestQueueTimeMs、LocalTimeMs、RemoteTimeMs、ThrottleTimeMs、含义

Kafka request.log中RequestQueueTimeMs、LocalTimeMs、RemoteTimeMs、ThrottleTimeMs、含义 要理解各个延时项的含义&#xff0c;必须从Kafka收到TCP请求、处理请求到返回TCP包整个流程开始梳理 RequestQueueTimeMs Processor 执行processNewResponses() 方法&#xff0c;不…

Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling

感想&#xff1a;由于看不懂官方代码的原因&#xff0c;自己这方面耽误了一段时间&#xff0c;一方面&#xff0c;在AI与经济学之间犹豫了许久&#xff0c;另一方面&#xff0c;工作 了半年&#xff0c;也没发工资&#xff0c;没空找培训代码的课程&#xff0c;所以停止更新了三…

wx.getUserProfile too frequently 问题

接口调用频率规范 概念介绍 小程序wx接口可分为“普通接口”和“限频接口”。 “限频接口”指的是一个用户在一段时间内不允许频繁调用的wx接口&#xff0c;此类接口一般会调用到微信后台系统资源&#xff0c;为了保护系统&#xff0c;同时防止用户资源被滥用&#xff0c;开…

软件测试基础概念

什么是需求 什么是需求&#xff1f;简单来说就是我想吃饭&#xff0c;这件事就是我的需求&#xff0c;我不想上课&#xff0c;这也是我的需求。对于软件测试来说&#xff0c;需求可以分为用户需求和软件需求。 用户需求 用户需求简单可以理解为甲方提出的要求&#xff0c;如…

git基础教程(linux)

1.git简介 git 分布式版本控制 git两大特点&#xff1a; 版本控制&#xff1a;支持多人同时开发 分布式&#xff1a; 2.安装与配置 安装 sudo apt-get install git安装成功&#xff0c;运行如下命令&#xff1a; git3.创建一个版本库 (1)新建一个目录git_test&#xff0c…

zabbix服务部署

文章目录 zabbix1 zabbix简介1.1 组成部件1.2 监控原理1.3 Zabbix 6.0新特性1.4 Zabbix6.0功能组件1.4.1 Zabbix Server1.4.2 数据库1.4.3 Web界面1.4.4 Zabbix Agent1.4.5 Zabbix Proxy1.4.6 Java Gateway 2 部署zabbix服务端2.1 部署Nginx2.2 安装PHP2.3 修改Nginx配置2.4 修…

找工作不用愁!送你一份Salesforce顾问面试秘籍(下)(含答案)

作为SaaS行业的先驱&#xff0c;Salesforce的发展一路高歌猛进。在Salesforce生态系统中不仅能学习到最新的技术&#xff0c;而且比其他行业的同岗位享有更高的薪水&#xff0c;这也驱使了越来越多人加入Salesforce大军。 在之前的文章中&#xff0c;自由侠部落为学习者梳理了…

奥威BI-金蝶云星空SaaS版一站式平台:对接数据、做分析

金蝶云星空和BI大数据分析平台都在企业数字化转型中扮演了重要的角色&#xff0c;为企业提供了全面的数字化解决方案和数据分析功能&#xff0c;两者强强联合不仅能提高部署效率&#xff0c;更能增强数据分析、数据可视化效果&#xff0c;帮助企业更好地适应市场变化和用户需求…

Arcgis Pro NDVI(植被指数)导出RGB

在arcgis中计算的NDVI栅格数据&#xff0c;取值范围为-1到1&#xff0c;直接导出JPG或者PNG&#xff0c;会出现导出错误的问题&#xff1a; 导出出错&#xff0c; 设置导出格式为TIFF&#xff0c;然后选中使用渲染器&#xff0c;勾选强制RGB颜色&#xff0c;即可导出你选择的色…

【C++STL】list的反向迭代器

list的反向迭代器 文章目录 list的反向迭代器reverse.h疑问1&#xff1a;为什么在迭代器当中不需要写深拷贝、析构函数疑问2&#xff1a;为什么在迭代器当中需要三个模板参数&#xff1f;疑问3&#xff1a;反向迭代器是怎么实现的&#xff1f;疑问4&#xff1a;为什么*解引用不…

创建UI组件库后上传NPM

上篇已经讲了如何创建自己的组件库&#xff0c;这篇讲怎么上传npm后&#xff0c;可以下载使用 1.首先看下组件的文件结构 在index.js中要写上每个组件可以按需引用的条件 import Button from "./src/button";Button.install function(Vue) {Vue.component(Button.…

Kubernetes 容器类型 Init - pause - sidecar - app容器

目录 Kubernetes 的容器类型 Init 初始化容器 参考文档&#xff1a;Init 容器 | Kubernetes 使用 Init 容器的情况 案例&#xff1a;定义了一个具有 2 个 Init 容器的简单 Pod 你通过运行下面的命令启动 Pod&#xff1a; 发现两个Init容器都没有运行成功 查看更多详细…