设计模式之访问者模式:一楼千面 各有玄机

在这里插入图片描述

~犬📰余~

“我欲贱而贵,愚而智,贫而富,可乎?
曰:其唯学乎”

一、访问者模式概述

\quad 江湖中有一个传说:在遥远的东方,有一座神秘的玉楼。每当武林中人来访,楼中的各个房间都会根据来访者的身份展现出不同的面貌。练剑之人来访,便见剑术精要;习医之人来访,则现医道真谛。一样的楼阁,却能因来访者的不同而呈现万千气象。这,正是访问者模式的真谛。
\quad 在软件设计的世界里,访问者模式就像这座神奇的玉楼。它允许我们将数据结构和数据操作分离,就像将楼阁和访客分开一样。这种设计模式定义了一种方式,让我们能够在不改变已有对象结构的情况下,向其中添加新的操作行为。
\quad 想象一下游乐园的场景:过山车、旋转木马、海盗船等设施早已固定在那里,但每天都会有不同的人来访问它们 —— 游客来游玩、检查员来检修、维护工来保养。每类访问者都会对这些设施进行不同的操作,但设施本身的结构并不会因此改变。

二、访问者模式的角色组成

\quad 在解析访问者模式的角色构成之前,让我们先看一下它的整体结构::

图片
\quad 就像一座精心设计的园林,访问者模式中的每个角色都各司其职,共同构建出一个优雅的结构体系。让我们一起走进这座代码园林,认识一下其中的主要角色:

  • Element(元素):它就像游乐园中的各个游乐设施。每个Element都定义了一个accept方法,这个方法就像设施的接待窗口,来访者必须通过这个窗口才能与设施互动。在我们的游乐园例子中,它可以是过山车、旋转木马等具体设施。
  • Visitor(访问者):它就像是来游乐园的不同人员。可能是来玩耍的游客、来检修的工程师,或是来检查安全的督察员。每种访问者都定义了一系列visit方法,用于访问不同类型的元素。这些方法就像是不同人员对设施的不同操作方式。
  • ObjectStructure(对象结构):像是整个游乐园的管理处。它知道园内有哪些设施,并且负责安排访问者去访问这些设施。当一个安全检查员来到游乐园时,管理处会安排他依次检查所有的设施。
  • ConcreteElement(具体元素):是Element的实现类,就像具体的过山车、旋转木马。它们都实现了accept方法,在方法中通过调用访问者的visit方法来完成具体的操作。这就像每个设施都知道如何配合不同人员的工作。
  • ConcreteVisitor(具体访问者):Visitor的实现类,例如具体的安全检查员、维修工程师等。他们各自实现了visit方法,定义了对不同设施的具体操作流程。检查员检查安全隐患,工程师进行维护保养,各司其职。

\quad 这些角色之间的互动就像是一场精心编排的舞蹈:当游客(ConcreteVisitor)来到游乐园(ObjectStructure)时,管理处会安排他们依次游览各个设施(ConcreteElement)。每个设施都会根据访问者的身份,展现出相应的互动方式。

三、访问者模式案例

\quad 让我们通过一个完整的游乐园管理系统来深入理解访问者模式。在这个系统中,我们需要对不同的游乐设施进行日常检查和维护。每种设施都有其特定的检查点,而不同的工作人员(访问者)也有着不同的工作职责。
\quad 首先,让我们定义设施接口和具体设施:

// 设施接口
public interface Facility {void accept(FacilityVisitor visitor);
}// 过山车设施
public class RollerCoaster implements Facility {private String name;private int maxSpeed;public RollerCoaster(String name, int maxSpeed) {this.name = name;this.maxSpeed = maxSpeed;}public String getName() { return name; }public int getMaxSpeed() { return maxSpeed; }@Overridepublic void accept(FacilityVisitor visitor) {visitor.visit(this);}
}// 旋转木马设施
public class Carousel implements Facility {private String name;private int capacity;public Carousel(String name, int capacity) {this.name = name;this.capacity = capacity;}public String getName() { return name; }public int getCapacity() { return capacity; }@Overridepublic void accept(FacilityVisitor visitor) {visitor.visit(this);}
}// 访问者接口
public interface FacilityVisitor {void visit(RollerCoaster rollerCoaster);void visit(Carousel carousel);
}// 安全检查员
public class SafetyInspector implements FacilityVisitor {@Overridepublic void visit(RollerCoaster rollerCoaster) {System.out.println("安全检查员正在检查过山车 " + rollerCoaster.getName());System.out.println("检查最高速度: " + rollerCoaster.getMaxSpeed() + "km/h");System.out.println("检查安全带和刹车系统...");}@Overridepublic void visit(Carousel carousel) {System.out.println("安全检查员正在检查旋转木马 " + carousel.getName());System.out.println("检查承载人数: " + carousel.getCapacity() + "人");System.out.println("检查座椅固定装置...");}
}// 维护工程师
public class MaintenanceEngineer implements FacilityVisitor {@Overridepublic void visit(RollerCoaster rollerCoaster) {System.out.println("维护工程师正在保养过山车 " + rollerCoaster.getName());System.out.println("润滑轨道和车轮...");System.out.println("检测电机运行状态...");}@Overridepublic void visit(Carousel carousel) {System.out.println("维护工程师正在保养旋转木马 " + carousel.getName());System.out.println("检查驱动系统...");System.out.println("更换磨损零件...");}
}// 游乐园管理类
public class AmusementPark {private List<Facility> facilities = new ArrayList<>();public void addFacility(Facility facility) {facilities.add(facility);}public void accept(FacilityVisitor visitor) {for(Facility facility : facilities) {facility.accept(visitor);}}
}

\quad 现在让我们通过一个具体的例子来运行这个系统:

public class Test{public static void main(String[] args) {// 创建游乐园AmusementPark park = new AmusementPark();// 添加设施park.addFacility(new RollerCoaster("极速之星", 120));park.addFacility(new Carousel("童话木马", 30));// 创建访问者SafetyInspector inspector = new SafetyInspector();MaintenanceEngineer engineer = new MaintenanceEngineer();// 进行安全检查System.out.println("=== 开始安全检查 ===");park.accept(inspector);System.out.println("\n=== 开始设备维护 ===");park.accept(engineer);}
}

\quad 运行这段代码,我们可以看到不同的访问者对相同设施进行不同的操作,而不需要修改设施类的代码:
在这里插入图片描述

四、访问者模式优缺点

4.1. 优点:

\quad 访问者模式最显著的特点是实现了数据结构与数据操作的分离。就像我们的游乐园案例,无论是增加新的检查员还是维护工程师,都不需要修改原有的设施类代码。这种设计非常符合"开闭原则",对扩展开放,对修改关闭。同时,相关的操作行为被集中在访问者类中,使得操作逻辑更加集中和清晰。例如,所有的安全检查逻辑都在SafetyInspector类中,便于统一管理和维护。

4.2. 缺点:

\quad 首先是对扩展元素类型不友好。如果我们要在游乐园中增加一种全新的设施类型,就需要修改所有现有的访问者类,添加相应的visit方法。这违反了"开闭原则"。其次,访问者模式要求元素类的内部结构对访问者是可见的。比如检查员需要知道过山车的最高速度、旋转木马的承载人数等属性,这在某种程度上破坏了对象的封装性。
\quad 此外,使用访问者模式可能会导致系统变得更复杂。我们需要维护多个访问者类,它们之间可能存在一些交叉的职责。比如安全检查和维护工作可能会有重叠的检查项目,这时就需要考虑如何合理划分职责。

五、访问者模式的适用场景

\quad 访问者模式就像是一位经验丰富的管家,最适合处理"对象结构相对稳定,但操作多种多样"的场景。除了我们讨论的游乐园管理系统,它在许多其他领域也有着广泛的应用。
\quad 比如在编译器设计中,语法树的结构一旦确定就不会改变,但我们需要对语法树进行词法分析、语法分析、代码生成等多种操作。又如在文档处理系统中,文档结构(段落、章节、图表等)相对固定,但我们需要对文档进行打印、预览、格式转换等不同操作。
\quad 当你发现系统中有一个复杂的对象结构,而且经常需要对这些对象进行不同的操作时,不妨考虑使用访问者模式。但如果对象结构经常变动,或者操作比较单一,使用访问者模式可能会适得其反。

六、总结

\quad 访问者模式,讲究的是进退有度,相互尊重。它通过巧妙的设计,让数据结构与数据操作得以分离,就像是让每位访客都能以最适合的方式与主人互动。
\quad 在实际应用中,我们要明智地选择是否使用访问者模式。当面对稳定的对象结构和多变的操作需求时,访问者模式如同一位老成持重的管家,能够有条不紊地处理各种访客的需求。但如果对象结构经常变动,或者操作相对单一,使用访问者模式反而会使系统变得臃肿复杂。
\quad 正如古人云:万物有度,过犹不及。设计模式也是如此,关键在于找到最适合当前场景的解决方案。访问者模式,不过是我们设计工具箱中的一件利器,懂得何时使用,方能游刃有余。

在这里插入图片描述

关注犬余,共同进步

技术从此不孤单

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

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

相关文章

SAP月结、年结前重点检查事项(后勤与财务模块)

文章目录 一、PP生产模块相关的事务检查二、SD销售模块相关的事务检查:三、MM物料管理模块相关的事务检查四、FICO财务模块相关的事务检查五、年结前若干注意事项【SAP系统PP模块研究】 #SAP #生产订单 #月结 #年结 一、PP生产模块相关的事务检查 1、月末盘点后,生产用料的…

JVM实战—6.频繁YGC和频繁FGC的后果

大纲 1.JVM GC导致系统突然卡死无法访问 2.什么是Young GC什么是Full GC 3.Young GC、Old GC和Full GC的发生情况 4.频繁YGC的案例(G1解决大内存YGC过慢) 5.频繁FGC的案例(YGC存活对象S区放不下) 6.问题汇总 1.JVM GC导致系统突然卡死无法访问 (1)基于JVM运行的系统最怕…

蓝牙|软件 Qualcomm S7 Sound Platform开发系列之初级入门指南

本文适用范围 ADK24.2~ 问题/功能描述 S7开发环境搭建与编译介绍 实现方案 本文介绍适用于windows平台Application部分,audio ss的说明会在下一篇文章在做说明,Linux平台如果不进行AI算法的开发,个人认知是没有必要配置,若是做服务器倒是不错的选择.因为编译完成后烧录调试还…

LabVIEW冷却风机性能测试系统

开发了基于LabVIEW软件及LabSQL工具包的冷却风机性能测试系统。系统通过高效的数据库访问技术&#xff0c;实现了对冷却风机测试过程中关键性能数据的采集、存储与管理&#xff0c;优化了测试流程并提升了数据处理的效率。 ​ 项目背景 在工业生产和科研测试中&#xff0c;准…

C 实现植物大战僵尸(四)

C 实现植物大战僵尸&#xff08;四&#xff09; C 实现植物大战僵尸&#xff0c;完结撒花&#xff08;还有个音频稍卡顿的性能问题&#xff0c;待有空优化解决&#xff09;。目前基本的功能模块已经搭建好了&#xff0c;感兴趣的友友可自行尝试编写后续游戏内容 因为 C 站不能…

车间管理:掌握方法,有效应对浪费

在制造企业中&#xff0c;车间的有效管理对于提高生产效率、降低成本以及提升产品质量至关重要&#xff0c;然而面对外部激烈的市场竞争&#xff0c;利润微薄&#xff0c;内部车间却充满了各种浪费&#xff0c;企业管理者头痛不已&#xff0c;如果能有效改进内部车间浪费&#…

Logo设计免费生成器工具:轻松创建独特标志

在当今的商业世界中&#xff0c;一个独特且引人注目的Logo是任何企业或品牌的身份象征。它不仅代表了公司的形象&#xff0c;还传达了公司的价值观和使命。然而&#xff0c;对于许多初创企业或小型企业来说&#xff0c;聘请专业设计师来设计一个Logo可能是一笔不小的开销。这时…

【智行安全】基于Synaptics SL1680的AI疲劳驾驶检测方案

随著车载技术的快速进步&#xff0c;驾驶安全越来越受到重视&#xff0c;而疲劳驾驶是造成交通事故的重要原因之一。传统的驾驶监控技术因精度不足或反应迟缓&#xff0c;无法满足实时监测需求。因此&#xff0c;结合人工智能技术的疲劳驾驶检测系统成为行业新方向&#xff0c;…

uni-ui样式修改

因为之前官网uni-ui有些组件的样式不好看&#xff0c;所以要做一些调整&#xff0c;做个记录。用分段器举例~ 官网原生样式 调整后的 首先找到我们的static文件夹&#xff0c;里面一般存着项目的全局样式文件&#xff0c;没有的话自己创一个 uniui.scss /deep/ .segmented-con…

大模型WebUI:Gradio全解系列9——Additional Features:补充特性(下)

大模型WebUI&#xff1a;Gradio全解系列9——Additional Features&#xff1a;补充特性&#xff08;下&#xff09; 前言本篇摘要8. Additional Features&#xff1a;补充特性8.5 分享demo8.5.1 嵌入托管 Spaces8.5.2 使用 Web Components 嵌入8.5.3 Embedding with IFrames 8.…

计算机网络 (17)点对点协议PPP

一、PPP协议的基本概念 PPP协议最初设计是为两个对等节点之间的IP流量传输提供一种封装协议&#xff0c;它替代了原来非标准的第二层协议&#xff08;如SLIP&#xff09;。在TCP/IP协议集中&#xff0c;PPP是一种用来同步调制连接的数据链路层协议&#xff08;OSI模式中的第二层…

HTML5滑块(Slider)

HTML5 的滑块&#xff08;Slider&#xff09;控件允许用户通过拖动滑块来选择数值。以下是如何实现一个简单的滑块组件的详细说明。 HTML5 滑块组件 1. 基本结构 使用 <input type"range"> 元素可以创建一个滑块。下面是基本实现的代码示例&#xff1a; <…

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件

在Linux上获取MS(如Media Server)中的RTP流并录制为双轨PCM格式的WAV文件 一、RTP流与WAV文件格式二、实现步骤三、伪代码示例四、C语言示例代码五、关键点说明六、总结在Linux操作系统上,从媒体服务器(如Media Server,简称MS)获取RTP(Real-time Transport Protocol)流…

Unity3D仿星露谷物语开发12之创建道具列表

1、目标 道具是游戏的核心部分&#xff0c;道具包括你可以拾取的东西&#xff0c;你可以使用的工具和你能种的东西等。 本节就是创建道具的信息类。同时了解ScriptableObject类的使用。 2、创建道具枚举类 修改Assets -> Scripts -> Enums.cs脚本&#xff0c; 新增如…

华为云Welink数据怎么连接到小满CRM?

Welink是什么&#xff1f;好用吗&#xff1f; 华为云WeLink是华为内部打磨多年的协同办公平台、远程办公软件、移动办公平台、协同办公软件&#xff0c;来源华为19万员工的数字化办公实践&#xff0c;融合多屏协同、打卡、报销、考勤、审批、企业网盘、IM消息、邮件、视频会议…

借助 FinClip 跨端技术探索鸿蒙原生应用开发之旅

在当今数字化浪潮汹涌澎湃的时代&#xff0c;移动应用开发领域正经历着深刻的变革与创新。鸿蒙操作系统的崛起&#xff0c;以其独特的分布式架构和强大的性能表现&#xff0c;吸引了众多开发者的目光。而FinClip 跨端技术的出现&#xff0c;为开发者涉足鸿蒙原生应用开发提供了…

IDEA+Docker一键部署项目SpringBoot项目

文章目录 1. 部署项目的传统方式2. 前置工作3. SSH配置4. 连接Docker守护进程5. 创建简单的SpringBoot应用程序6. 编写Dockerfile文件7. 配置远程部署 7.1 创建配置7.2 绑定端口7.3 添加执行前要运行的任务 8. 部署项目9. 开放防火墙的 11020 端口10. 访问项目11. 可能遇到的问…

Excel文件恢复教程:快速找回丢失数据!

Excel文件恢复位置在哪里&#xff1f; Excel是微软开发的电子表格软件&#xff0c;它为处理数据和组织工作提供了便捷。虽然数据丢失的问题在数字时代已经司空见惯&#xff0c;但对于某些用户来说&#xff0c;恢复未保存/删除/丢失的Excel文件可能会很困难&#xff0c;更不用说…

pyinstaller打包exe可执行文件

cd命令符进入要打包文件路径下&#xff0c;执行&#xff1a; 1.打包单个py文件&#xff0c;在控制台执行;dist下会生成2个文件&#xff0c;一个是exe文件 pyinstaller -D happy.py (cd命令符进入要打包文件路径下&#xff0c;执行) 打包单个py文件&#xff0c;在控制台执行;…

PDF怎么压缩得又小又清晰?5种PDF压缩方法

PDF 文件在日常办公与学习中使用极为频繁&#xff0c;可想要把它压缩得又小又清晰却困难重重。一方面&#xff0c;PDF 格式本身具有高度兼容性&#xff0c;集成了文字、图像、矢量图等多样元素&#xff0c;压缩时难以兼顾不同元素特性&#xff0c;稍不注意&#xff0c;文字就会…