设计模式|访问者模式(Visitor Pattern)

文章目录

  • 结构
  • 举例
  • 优缺点
    • 优点
    • 缺点
  • 代码示例
  • 常见面试题

访问者模式是一种行为设计模式,它允许在不改变已有类的情况下定义一组新的操作。
这些操作通常分散在不同的类中,但是希望能够对这些类的对象进行统一的处理。
访问者模式的核心思想是将操作从对象结构中分离出来,使得可以在不改变这些对象的前提下定义新的操作。

结构

访问者模式的结构包括以下主要组成部分:

  1. 抽象元素(Element):
  • 定义了一个接口,声明了接受访问者对象的accept方法,该方法通常以访问者作为参数。抽象元素可以是一个接口或抽象类,它定义了访问者可以访问的对象的通用接口。
  1. 具体元素(ConcreteElement):
  • 实现了抽象元素接口,提供了具体的实现,包含了具体的业务逻辑。每个具体元素都必须实现accept方法,该方法将自身作为参数传递给访问者。
  1. 抽象访问者(Visitor):
  • 定义了一个访问接口,声明了一组访问方法,每个方法对应一个具体元素的访问操作。抽象访问者可以是一个接口或抽象类,它定义了访问者可以执行的操作。
  1. 具体访问者(ConcreteVisitor):
  • 实现了抽象访问者接口,提供了具体的访问操作。每个具体访问者都必须实现抽象访问者中声明的所有访问方法,以便对具体元素进行访问。
  1. 对象结构(Object Structure):
  • 包含了一组具体元素对象,可以是一个集合、列表、树等数据结构。对象结构通常提供了一个接口或方法来允许访问者访问其中的元素。

通过以上组成部分的协作,访问者模式实现了对一个对象结构中的元素进行多种不同操作的能力,同时又保持了元素类和操作的解耦合。

举例

  1. 动物园游客参观动物: 想象你去动物园参观,动物园中有许多不同的动物,比如狮子、大象、长颈鹿等。你可以作为一个访问者,对每种动物进行不同的操作,比如观察、喂食、拍照等。这里的动物就是对象结构,而你的行为就是访问者模式中的访问者,可以对不同的动物执行不同的操作。
  2. 超市购物: 当你去超市购物时,你可能会购买不同种类的商品,比如水果、蔬菜、零食等。你可以把超市看作是一个对象结构,不同种类的商品是其中的元素,而你的购物清单就是访问者模式中的访问者,可以对不同种类的商品执行不同的操作,比如购买、放回货架等。
  3. 家庭医生给病人检查: 假设你去看家庭医生,医生可能会对你进行身体检查,比如量体温、听心跳、观察症状等。在这个例子中,你是医生的访问者,医生是对象结构,而不同的检查项目是医生可以执行的操作。

这些例子虽然简单,但可以帮助理解访问者模式的基本概念:访问者可以对一个对象结构中的元素执行不同的操作,而不需要修改元素的类。

优缺点

优点

  1. 分离关注点:访问者模式将数据结构和对数据结构的操作分离开来,使得各自的变化不会影响到对方,从而实现了关注点的分离。
  2. 新功能扩展方便:通过添加新的访问者类,可以很方便地在不改变现有类的情况下,扩展对数据结构的操作。
  3. 符合开闭原则:访问者模式通过在不改变现有代码的情况下,添加新的操作,符合开闭原则,使得系统更加容易扩展和维护。

缺点

  1. 增加新的元素类困难:如果要在系统中添加新的元素类,需要修改所有的访问者类,以便它们能够处理新的元素类。这违背了开闭原则,使得系统的扩展性降低。
  2. 破坏封装:访问者模式将数据结构的内部细节暴露给了访问者类,破坏了数据结构的封装性,使得数据结构更加脆弱。
  3. 可读性降低:访问者模式会导致系统中的类和类之间的关系变得更加复杂,降低了代码的可读性和可维护性。

综合考虑,访问者模式适用于对数据结构中的元素进行多种不同的操作,且数据结构的类层次比较稳定的情况下。但是,需要注意其可能带来的缺点,特别是在系统需要频繁扩展新的元素类时,可能会增加系统的维护成本。

代码示例

假设有一个几何图形类层次结构,包括圆形(Circle)和矩形(Rectangle),我们想要实现两种不同的操作:计算图形的面积和计算图形的周长。

首先,定义几何图形的接口和两种不同的访问者:

// 几何图形接口
interface Shape {void accept(Visitor visitor);
}// 圆形类
class Circle implements Shape {private double radius;public Circle(double radius)

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

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

相关文章

请把「睡一个好觉」,当成一天里最重要的事来管理

我发现许多人都有这么一种情况:明明知道睡眠很重要,但却总是有意无意地熬夜。 比如: 给自己排了太多的学习和工作量,一不小心就到了凌晨一两点; 总觉得过去的一天什么都没干,宁愿在网上闲逛,也不…

ChatGPT:提升写作效率的必备工具

ChatGPT无限次数:点击直达 html ChatGPT:提升写作效率的必备工具 作为一名有着10年经验的CSDN网站原创文章优质创作者,写作效率对我来说至关重要。在这篇文章中,我将分享如何利用ChatGPT这一强大工具提升写作效率,以及具体的实…

Nacos源码分析,Nacos如何注册一个服务实例?

作为SpringCloudAlibaba微服务架构实战派上下册和RocketMQ消息中间件实战派上下册的作者,我来给大家带来Nacos源码系列的技术文章。 HTTP方式注册服务实例 Naocs使用InstanceController类的HTTP方法register()提供注册服务实例的功能。 /*** 注册服务实例到注册中…

低代码开发平台权威推荐:创新开发、领跑市场!

Gartner是低代码领域的一家权威机构,该机构常常通过"魔力象限"的研究方法,评选全球范围内IT细分领域的产品,来帮助决策者提供重要的咨询建议。本文盘点了Gartner机构推荐的6款低代码平台:Zoho Creator、Mendix、Oracle、…

Java 中建造者模式,请用代码具体举例

建造者模式是一种创建型设计模式,它允许你创建一个复杂对象的不同部分并将它们组装在一起,以产生最终的对象。以下是一个简单的 Java 示例,演示了建造者模式的用法: // 产品类 class Computer {private String cpu;private String…

JVM结构化体系

目录 目录 1.JVM 简介 1.1. 如何理解 JVM 呢? 1.2. 市场主流 JVM 分析? 1.3. 为什么要学习 JVM? 1.4. 字节码底层是如何执行呢? 如何理解 JIT 呢? 为什么 JVM 中解释执行与编译执行的并存(混合模式&…

【C++】类和对象③(类的默认成员函数:拷贝构造函数 | 赋值运算符重载)

🔥个人主页:Forcible Bug Maker 🔥专栏:C 目录 前言 拷贝构造函数 概念 拷贝构造函数的特性及用法 赋值运算符重载 运算符重载 赋值运算符重载 结语 前言 本篇主要内容:类的6个默认成员函数中的拷贝构造函数…

el-drawer二次封装进行可拖拽

1.想要的效果 鼠标放到上面出现箭头显示可拖拽得图标 2.代码实现 2.1封装成自定义指令 // drawerDragDirective.js // 定义指令 const drawerDragDirective {// 指令绑定时的处理函数bind(el, ) {const minWidth 300;const dragDom el.querySelector(.el-drawer);// 创…

掀起区块链开发狂潮!Scaffold-eth带你一键打造震撼DApp

文章目录 前言一、Scaffold-eth是什么?二、安装和配置1.准备工作2.安装3.配置开发环境 三、进阶使用1.放入自己的合约2.部署运行 总结 前言 前面的文章传送🚪:hardhat入门 与 hardhat进阶 在之前的文章中,我们已经探讨了使用Har…

【Linux】提升Linux命令行效率:光标移动和文本操作的键盘快捷键

Just 那么年少 还那么骄傲 两眼带刀 不肯求饶 即使越来越少 即使全部都输掉 也要没心没肺地笑 Just 那么年少 我向你招手 让你看到 我混账到老 天涯海角 天荒地老 只等你摔杯为号 🎵 朴树《Forever Young》 Linux命令行界面(CLI&am…

设计模式系列:简单工厂模式

作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS二次开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 目录 定义 特点 使用场景 优缺点 (1) 优点…

故障转移-redis

4.4.故障转移 集群初识状态是这样的: 其中7001、7002、7003都是master,我们计划让7002宕机。 4.4.1.自动故障转移 当集群中有一个master宕机会发生什么呢? 直接停止一个redis实例,例如7002: redis-cli -p 7002 sh…

保持微软Microsoft Teams始终在线的方案

保持微软Microsoft Teams始终在线的方案 背景方案 背景 目前使用微软Teams办公的小伙伴很多,但是长时间不操作电脑就被自动设置成离线状态。对于在电脑前学习书本或者在思考问题的小伙伴就显得不太友好,因为即使我们不操作电脑我们也时刻在电脑前&#…

定时器产生延时停止

1,需求: 当按下按钮SB1,输出信号为0N,指示灯点亮;按下按钮SB2,经过10s的延时后,指示灯熄灭 2,关闭使用定时的常闭触电

Python 如何的调试模式使用 Python 的内置调试器 pdb 或者集成开发环境(IDE)如 PyCharm、Visual Studio Code

Python 的调试模式通常是通过使用 Python 的内置调试器 pdb 或者集成开发环境(IDE)如 PyCharm、Visual Studio Code 等中的调试工具来实现的。 使用 pdb pdb 是 Python 的标准库中的一个模块,它提供了一个交互式的源代码调试器。你可以使用…

Graphql mock 方案

GraphQL API 的强类型本质非常适合模拟。模拟是 GraphQL Code-First 开发过程的重要组成部分,它使前端开发人员能够构建 UI 组件和功能,而无需等待后端实现。 我们期望基于 TS 强类型定义的特点以及中后台常见列表、详情的数据类型共性,实现…

HG泄露(ctfhub)

工具准备:dirsearch、dvcs-ripper 网络安全之渗透测试全套工具篇(内含安装以及使用方法)_dvcs-ripper-CSDN博客 dvcs-ripper:一款perl的版本控制软件信息泄露利用工具,支持bzr、cvs、git、hg、svn... tree //树状…

APP开发_Android 与 js 互相调用

1 js 调用 Android 方法 当使用 JavaScript 调用 Android 原生方法时,主要涉及到 Android 的 WebView 组件,它允许你在 Android 应用中嵌入网页内容,并提供了 JavaScript 与 Android 代码交互的能力。 (1)创建JavaSc…

项目升级到jdk21后 SpringBoot相关组件的适配

了解到jdk21是一个LTS版本,可以稳定支持协程的功能。经过调研,将目前线上的jdk8升级到21,使用协程提升并发性能。 目前系统使用springBoot 2.0.3.RELEASE,并且引入了mybatis-spring-boot-starter、spring-boot-starter-data-redi…

MySql数据库从0-1学习-第四天多表查询

多表查询,指从多张表查询数据 连接查询 内连接: 相当于查询A和B交集部分数据外连接 左外连接: 查询左表所有的数据(包括两张表交集部分的数据)有外连接: 查询右表所有的数据(包括两张表交集部分的数据) 子查询 内连接查询 隐式内连接查询 select 字段列表 from 表1,表2 whe…