【设计模式-行为型】访问者模式

一、什么是访问者模式

        说起来访问者模式,其实很少用。我一直在思考该用什么样的例子把这个设计模式表述清晰,最近突然想到一个例子也许他就是访问者。港片有过很辉煌的年代,小的时候一直在看港片觉得拍的非常好,而且演员的演技也在线。 不知道大家看没有看过一个金典的穿越剧----《寻秦记》,其中的项少龙(古天乐)就是专业的访问者。项少龙的经历可以很好地体现访问者模式的核心思想。项少龙作为一个现代人,穿越到战国时期,他的角色可以被视为“访问者”,而战国时期的各种人物和事件可以被视为“元素”。项少龙与这些元素的交互“不改变历史结构,添加新的操作”,触发了一系列的变化和故事发展。

访问者模式在《寻秦记》中的体现

  1. 主角作为访问者:项少龙从21世纪穿越到战国时期,他的任务是寻找并保护嬴政,确保历史的正常发展。在这个过程中,他作为“访问者”,与战国时期的各种人物和事件进行交互。

  2. 元素的多样性:战国时期的人物和事件可以被视为“元素”,例如嬴政、乌廷芳、琴清、嫪毐等。每个元素都有其独特的属性和行为,项少龙需要与这些元素进行交互,以完成他的任务。

  3. 交互触发变化:项少龙与这些元素的交互,触发了一系列的变化。例如,他帮助嬴政成长,与乌廷芳和琴清建立了深厚的情感联系。这些交互不仅影响了项少龙自身,也影响了战国时期的历史进程。

  4. 历史轨迹的复杂性:尽管项少龙试图改变历史,但他最终发现历史的轨迹非常复杂,无法轻易改变。这体现了访问者模式中,访问者对元素的操作可能会受到元素自身复杂性的限制。

        访问者模式通过将操作(项少龙和战国时期任务和事件的交互)从对象结构(战国的历史轨迹)中分离出来,封装在访问者(项少龙)类中,使得可以在不修改对象结构的情况下为对象添加新的操作。这种模式特别适用于需要对对象结构中的元素执行多种操作的场景。

二、为什么用访问者模式

        我们来通过上述例子来看看为什么要使用访问者呢,或者什么样的场景使用到了访问者:

  1. 扩展性强:访问者模式能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。在《寻秦记》中,项少龙可以尝试不同的策略和方法来影响历史,而不需要改变历史本身的结构。

  2. 集中管理复杂逻辑:访问者模式将对各个元素的一组操作集中在一个访问者类当中。项少龙的行动和决策都围绕着他的目标展开,使得他的行为更加有条理和系统化。

  3. 解耦数据结构和操作:在《寻秦记》中,项少龙作为访问者,与战国时期的各种人物和事件(元素)进行交互,而不需要改变这些元素本身的结构。这使得项少龙可以灵活地尝试不同的策略,而不会对历史结构本身造成不可逆的影响。

  4. 支持多种操作:访问者模式允许在不修改对象结构的情况下,为对象结构中的元素添加新的操作。项少龙可以尝试多种方法来影响历史,例如通过政治手段、军事手段或情感手段,而不需要改变历史本身的结构。

  5. 对象结构比较稳定,但经常需要在此对象结构上定义新的操作

  6. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类

三、访问者模式示例

        下面我们拿项少龙的经历用代码带输出示例

1. 定义元素接口(各种任务或者事件的统一行为,必须接受访问者)(Element)

public interface Element {
    void accept(Visitor visitor);
}

2.实现具体元素类(具体的事件或者人物,比如嬴政)(ConcreteElement)

public class YingZheng implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void growWithXiangShaolong() {
        System.out.println("嬴政在项少龙的帮助下成长为一代帝王。");
    }
}

public class WuTingFang implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void developRelationshipWithXiangShaolong() {
        System.out.println("乌廷芳与项少龙建立了深厚的情感联系。");
    }
}

public class LaoAi implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void confrontXiangShaolong() {
        System.out.println("嫪毐与项少龙发生冲突。");
    }
}

3、定义访问者接口(访问者的统一行为)(Visitor)

public interface Visitor {
    void visit(YingZheng yingZheng);
    void visit(WuTingFang wuTingFang);
    void visit(LaoAi laoAi);
}

4. 实现具体访问者类(主角项少龙)(ConcreteVisitor) 

public class XiangShaolongVisitor implements Visitor {
    @Override
    public void visit(YingZheng yingZheng) {
        yingZheng.growWithXiangShaolong();
    }

    @Override
    public void visit(WuTingFang wuTingFang) {
        wuTingFang.developRelationshipWithXiangShaolong();
    }

    @Override
    public void visit(LaoAi laoAi) {
        laoAi.confrontXiangShaolong();
    }
}

5、场景复现(穿越大戏开始)

public class Main {
    public static void main(String[] args) {
        // 创建具体元素对象
        Element yingZheng = new YingZheng();
        Element wuTingFang = new WuTingFang();
        Element laoAi = new LaoAi();

        // 创建具体访问者对象
        Visitor xiangShaolong = new XiangShaolongVisitor();

        // 执行操作
        yingZheng.accept(xiangShaolong);
        wuTingFang.accept(xiangShaolong);
        laoAi.accept(xiangShaolong);
    }
}

//输出
嬴政在项少龙的帮助下成长为一代帝王。
乌廷芳与项少龙建立了深厚的情感联系。
嫪毐与项少龙发生冲突。

        通过这个代码示例,我们可以清晰地看到访问者模式的核心优势。访问者模式通过将操作从对象结构中分离出来,封装在访问者类中,使得可以在不修改对象结构的情况下为对象添加新的操作。这种模式特别适用于需要对对象结构中的元素执行多种操作的场景,例如项少龙在战国时期与不同角色的交互。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

appium自动化环境搭建

一、appium介绍 appium介绍 appium是一个开源工具、支持跨平台、用于自动化ios、安卓手机和windows桌面平台上面的原生、移动web和混合应用,支持多种编程语言(python,java,Ruby,Javascript、PHP等) 原生应用和混合应用&#xf…

vue3组件el-table报错

传给table标签的data不是数组就会报错, 摁着商品管理代码找了半天也没发现哪里错了,而且关闭报错表格数据能正常显示, 。。。 最后发现我还有个订单管理页面,这里面的data初始化成ref( )了,把这个组件注释掉&#xf…

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言: 本片博客只讲述了操作的大致流程,具体实现步骤并不标准,请以参考为准。 本文前提:熟悉使用webSocket 如果大家还不了解什么是WebSocket,可以参考我的这篇博客: rWebSocket 详解:全双工…

《边界感知的分而治之方法:基于扩散模型的无监督阴影去除解决方案》学习笔记

paper:Boundary-Aware Divide and Conquer: A Diffusion-Based Solution for Unsupervised Shadow Removal 目录 摘要 1、介绍 2、相关工作 2.1 阴影去除 2.2 去噪扩散概率模型(Denoising Diffusion Probabilistic Models, DDPM) 3、方…

linux-mysql在centos7安装和基础配置

1.安装mysql数据库 1.使用官网安装 1.检查是否存在mysql的分支mariadb [rootlocalhost ~]# rpm -qa |grep mariadb mariadb-libs-5.5.64-1.el7.x86_64 [rootlocalhost ~]# 2.卸载这个分支包 [rootlocalhost ~]# rpm -qa | grep mariadb mariadb-libs-5.5.64-1.el7.x86_64 …

Python!从0开始学爬虫:(一)HTTP协议 及 请求与响应

前言 爬虫需要基础知识,HTTP协议只是个开始,除此之外还有很多,我们慢慢来记录。 今天的HTTP协议,会有助于我们更好的了解网络。 一、什么是HTTP协议 (1)定义 HTTP(超文本传输协议&#xff…

MySQL数据库笔记——最左前缀原则原理及其注意事项

大家好,这里是Good Note,关注 公主号:Goodnote,专栏文章私信限时Free。本文详细介绍MySQL索引的关键潜规则——最左前缀原则。 文章目录 图示单值索引和联合索引单值索引联合索引 最左前缀原则示例分析1. 全值匹配查询时2. 匹配左…

Java数据结构 (链表反转(LinkedList----Leetcode206))

1. 链表的当前结构 每个方框代表一个节点,每个节点包含两个部分: 左侧的数字:节点存储的值,例如 45、34 等。右侧的地址(如 0x90):表示该节点 next 指针指向的下一个节点的内存地址。 例子中&a…

IMX6ull项目环境配置

文件解压缩: .tar.gz 格式解压为 tar -zxvf .tar.bz2 格式解压为 tar -jxvf 2.4版本后的U-boot.bin移植进SD卡后,通过串口启动配置开发板和虚拟机网络。 setenv ipaddr 192.168.2.230 setenv ethaddr 00:04:9f:…

git基础指令大全

版本控制 git管理文件夹 进入要管理的文件夹 — 进入 初始化(提名) git init 管理文件夹 生成版本 .git ---- git在管理文件夹时,版本控制的信息 生成版本 git status 检测当前文件夹下的文件状态 (检测,检测之后就要管理了…

[高等数学学习记录]函数的极值与最大值最小值

1 知识点 1.1 函数的极值及其求法 定义 设函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0​ 的某邻域 U ˚ ( x 0 ) \mathring{U}(x_0) U˚(x0​) 内有定义&#xff0c;如果对于去心邻域 U ˚ ( x 0 ) \mathring{U}(x_0) U˚(x0​) 内的任一 x x x&#xff0c;有 f ( x ) <…

docker 简要笔记

文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…

JVM常见知识点

在《深入理解Java虚拟机》一书中&#xff0c;介绍了JVM的相关特性。 1、JVM的内存区域划分 在真实的操作系统中&#xff0c;对于地址空间进行了分区域的设计&#xff0c;由于JVM是仿照真实的机器进行设计的&#xff0c;那么也进行了分区域的设计。核心区域有四个&#xff0c;…

电脑系统bcd文件损坏修复方法:小白也会的修复方法

电脑系统bcd文件损坏怎么办?当电脑开机时出现bcd文件损坏&#xff0c;一般情况是由于电脑系统的引导坏了&#xff0c;需要进行修复。现在越来越多的小伙伴遇到电脑引导丢失或者安装后无法正常引导的问题&#xff0c;我们现在一般是pe下进行修复引导&#xff0c;那么电脑系统bc…

Flutter_学习记录_导航和其他

Flutter 的导航页面跳转&#xff0c;是通过组件Navigator 和 组件MaterialPageRoute来实现的&#xff0c;Navigator提供了很多个方法&#xff0c;但是目前&#xff0c;我只记录我学习过程中接触到的方法&#xff1a; Navigator.push(), 跳转下一个页面Navigator.pop(), 返回上一…

【架构面试】二、消息队列和MySQL和Redis

MQ MQ消息中间件 问题引出与MQ作用 常见面试问题&#xff1a;面试官常针对项目中使用MQ技术的候选人提问&#xff0c;如如何确保消息不丢失&#xff0c;该问题可考察候选人技术能力。MQ应用场景及作用&#xff1a;以京东系统下单扣减京豆为例&#xff0c;MQ用于交易服和京豆服…

Git 如何将旧仓库迁移新仓库中,但不显示旧的提交记录

一、异常错误 场景&#xff1a;我想把旧仓库迁移新仓库中&#xff0c;放进去之后&#xff0c;新仓库会显示这个项目之前的所有提交&#xff0c;如何不显示这些旧的提交&#xff1f; 二、原因 我们需要将旧仓库迁移新仓库中&#xff0c;但是又不想在新仓库中显示旧的提交记录…

02-AD-绘制原理图(画示意图+添加已有P封装)

画示意图添加已有P封装 画原理示意图绘制原理图:电容绘制原理图:晶体绘制发光二极管绘制TVS二极管绘制按键绘制拨码开关绘制双排针绘制单排针绘制TYPE母座画图技巧:按顺序递增,删除不用的先画线,再画框 绘制AMS芯片填充框透明显示:防止遮挡其他部分不需要添加其他内容 绘制STM3…

C++红黑树详解

文章目录 红黑树概念规则为什么最长路径不超过最短路径的二倍&#xff1f;红黑树的时间复杂度红黑树的结构插入叔叔节点情况的讨论只变色(叔叔存在且为红)抽象的情况变色单旋&#xff08;叔叔不存在或叔叔存在且为黑&#xff09;变色双旋&#xff08;叔叔不存在或叔叔存在且为黑…

LLaMA-Factory 微调LLaMA3

LLaMA-Factory 框架 首先需要通过vscode连接远程服务器哦 如果是租赁的AutoDL服务器&#xff0c;一定要将模型下载到数据盘。 git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e . 准备训练数据 训练数据&#xff1a; fintech.json …