访问者模式(十八)

news2024/10/7 2:20:20

相信自己,请一定要相信自己

上一章简单介绍了命令模式(十七), 如果没有看过, 请观看上一章

一. 访问者模式

引用 菜鸟教程里面访问者模式介绍: https://www.runoob.com/design-pattern/visitor-pattern.html

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。

通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。

根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作

一.一 介绍

意图: 主要将数据结构与数据操作分离。

主要解决: 稳定的数据结构和易变的操作耦合问题。

何时使用: 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。

如何解决: 在被访问的类里面加一个对外提供接待访问者的接口。

关键代码: 在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。

应用实例: 您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。

缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

注意事项: 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。


组成角色具体关系
抽象访问者(Visitor)角色Action一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素
具体访问者(ConcreteVisitor)角色FailAction, SuccessAction实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么
抽象元素(Element)角色Person声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数
具体元素(ConcreteElement)角色Man WoMan实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作
对象结构(Object Structure)角色ObjectStructure是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现

image-20230615171102299

二. 访问者实例

二. 一 抽象访问者 Action

public abstract class Action {

    public abstract void getManResult (Man man);

    public abstract void getWomanResult(WoMan woMan);
}

二.二 具体访问者实现

二.二.一 差

@Slf4j
public class FailAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{}评价差",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生评价{}差",woMan.getName());
    }
}

二.二.二 优

@Slf4j
public class SuccessAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{}评价优秀",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生评价{}优秀",woMan.getName());
    }
}

二.二.三 待评价

@Slf4j
public class WaitAction extends Action{

    @Override
    public void getManResult(Man man) {
        log.info("男生{} 待评价",man.getName());
    }

    @Override
    public void getWomanResult(WoMan woMan) {
        log.info("女生{}待评价",woMan.getName());
    }
}

二.三 抽象元素 Person

@EqualsAndHashCode(of = {"name"})
public abstract class Person {
    private String name;

    public abstract  void accept(Action action);

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

二.四 具体元素

二.四.一 男人

public class Man extends Person{
    public Man (String name) {
        super.setName(name);
    }
    @Override
    public void accept(Action action) {
        action.getManResult(this);
    }
}

二.四.二 女人

public class WoMan extends Person{
    public WoMan (String name) {
       super.setName(name);
    }
    @Override
    public void accept(Action action) {
        action.getWomanResult(this);
    }
}

二.五 对象结构 ObjectStructure

public class ObjectStructure {

    private List<Person> personList = new ArrayList<>();

    public void accept( Person person) {
        personList.add(person);
    }

    public void remove(Person person) {
        personList.remove(person);
    }

    public void display (Action action) {
        for (Person person : personList) {
            person.accept(action);
        }
    }
}

二.六 测试

@Test
    public void oneTest() {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.accept(new Man("张三"));
        // 是成功的
        objectStructure.display(new SuccessAction());

        objectStructure.remove(new Man("张三"));
        objectStructure.accept(new Man("李四"));

        objectStructure.display(new FailAction());

        objectStructure.remove(new Man("李四"));
        objectStructure.accept(new WoMan("王二"));
        objectStructure.accept(new WoMan("麻子"));

        objectStructure.display(new WaitAction());

    }

image-20230615171718905

优点:

  1. 访问者模式符合单一职责原则、让程序具有优秀的扩展性、灵活性非常高

  2. 访问者模式可以对功能进行统一,可以做报表、UI、拦截器与过滤器,适用于数据结构相对稳定的系统

缺点:

  1. 具体元素对访问者公布细节,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的, 这样造 成了具体元素变更比较困难

  2. 违背了依赖倒转原则。访问者依赖的是具体元素,而不是抽象元素

  3. 因此,如果一个系统有比较稳定的数据结构,又有经常变化的功能需求,那么访问者模式就是比较合适的.


本章节的代码放置在 github 上:


https://github.com/yuejianli/DesignPattern/tree/develop/Visitor


谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!

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

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

相关文章

大模型入门(六)—— RLHF微调大模型

一、RLHF微调三阶段 参考&#xff1a;https://huggingface.co/blog/rlhf 1&#xff09;使用监督数据微调语言模型&#xff0c;和fine-tuning一致。 2&#xff09;训练奖励模型     奖励模型是输入一个文本序列&#xff0c;模型给出符合人类偏好的奖励数值&#xff0c;这个奖…

大数据技术——用户与组管理

一、实验目的 1.了解linux用户和组 2.熟练掌握liunx用户和组的基本操作 3.进一步了解linux系统 二、实验内容 1.用户账号的添加、删除与修改。 2.用户口令的管理 3.用户组的管理 三、实验原理或流程 Linux系统是一个多用户多任务的分时操作系统&#xff0c;任何一个要使…

阿里面试了7轮...就这么狠的吗?

引言 今年的大环境非常差&#xff0c;互联网企业裁员的现象比往年更严重了&#xff0c;可今年刚好是我的第一个“五年计划”截止的时间点&#xff0c;说什么也不能够耽搁了&#xff0c;所以早早准备的跳槽也在疫情好转之后开始进行了。但是&#xff0c;不得不说&#xff0c;这…

ApacheStreamPark2.1.0部署及执行flink-cdc任务同步mysql表的数据到es的实践

文章目录 [toc] 1.ApacheStreamPark是什么&#xff1f;2.介绍2.1 特性2.2 架构2.3 Zeppelin和StreamPark的对比 3.相关连接4.部署4.1 二进制包编译构建4.2 镜像构建4.3 初始化sql4.4 部署4.4.1 Docker-compose.yaml部署脚本4.4.2 配置文件准备4.4.3 flink启动配置4.4.4 streamp…

7. WebGPU 将图像导入纹理

我们在上一篇文章中介绍了有关使用纹理的一些基础知识。在本文中&#xff0c;我们将介绍从图像导入纹理。 在上一篇文章中&#xff0c;通过调用 device.createTexture 创建了一个纹理&#xff0c;然后通过调用 device.queue.writeTexture 将数据放入纹理中。 device.queue 上还…

从小白到大神之路之学习运维第41天---第三阶段---Redis高可用集群(redis 的主从复制、redis的哨兵模式操作)

第三阶段基础 时 间&#xff1a;2023年6月15日 参加人&#xff1a;全班人员 内 容&#xff1a; Redis高可用集群 目录 一、redis主从复制原理介绍 主从复制特点&#xff1a; 主从复制实现原理&#xff1a; 二、主从复制实现操作&#xff08;多机实例实现&#xff09…

Mysql 表的七种联接方式【附带练习sql】

联接 七种JOIN介绍 图形联接方式说明SQL内联接共有部分SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.Key B.Key;左联接A表独有共有部分SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key B.Key;右联接B表独有共有部分SELECT &…

linux spi相关调试

在Linux系统中&#xff0c;SPI 的用户模式设备接口的驱动源码位于 drivers/spi/spidev.c&#xff0c;在应用层生成 /dev/spidev* 的节点&#xff0c;可以通过 read、 write 达到与硬件设备的 SPI 通信。下面介绍spidev驱动移植和应用程序编写方法。 SPI &#xff08;serial pe…

阿里 P8 面试官总结的《2023 最新 java 面试题》限时开源了

国内的互联网面试&#xff0c;恐怕是现存的、最接近科举考试的制度。 以美国为例&#xff0c;北美工程师面试比较重视算法&#xff08;Coding&#xff09;&#xff0c;近几年也会加入 Design 轮&#xff08;系统设计和面向对象设计 OOD&#xff09;和 BQ 轮&#xff08;Behavi…

怎么学习数据库的相关知识? - 易智编译EaseEditing

学习数据库的相关知识可以按照以下步骤进行&#xff1a; 确定学习目标&#xff1a; 了解数据库的基本概念、原理和常用术语&#xff0c;学习数据库管理系统&#xff08;DBMS&#xff09;的功能和特性&#xff0c;以及掌握数据库设计和查询语言等方面的知识。 学习数据库基础知…

【闭包函数与装饰器大全】——python基础

目录索引 闭包&#xff1a;闭包三要素&#xff1a;闭包的作用&#xff1a;闭包演示&#xff1a;闭包的意义&#xff1a; 装饰器&#xff1a;特点&#xff1a;实例演示&#xff1a;实例演示2之参数&#xff1a; 装饰器常用的场景&#xff1a;编写一个计时的装饰器&#xff1a;*普…

AIGC和虚拟现实为什么必然产物

背景 在流量存量时代&#xff0c;内容运营重要性不言而喻。在流量时代&#xff0c;内容可以不要过于多样化和差异化&#xff0c;只需要有足够多的人流量&#xff0c;按流量转化比率来看&#xff0c;1000个人有1%概率转化&#xff0c;素材不变只要增加足够多的流量那就一定会有…

永久存储:文件处理与路径处理

&#x1f4e2;博客主页&#xff1a;盾山狂热粉的博客_CSDN博客-C、C语言,机器视觉领域博主&#x1f4e2;努力努力再努力嗷~~~✨ &#x1f4a1;大纲 ⭕如何将数据永久的存放到硬盘上 &#x1f449;不要打开文件&#xff0c;然后直接关闭文件&#xff0c;会导致截断 一、如何操作…

OneNote支持Markdown:高亮代码

文章目录 结论在前效果安装日常工作流&#xff08;高亮代码块&#xff09; 结论在前 markdown对我来说是伪需求&#xff0c;真正需要的是高亮代码&#xff0c;通过Github/NoteHighlight2016这个开源插件可实现这个插件虽然叫2016&#xff0c;但实测onenote 2013也是可以用的 效…

华为OD机试之数组去重和排序(Java源码)

数组去重和排序 题目描述 给定一个乱序的数组&#xff0c;删除所有的重复元素&#xff0c;使得每个元素只出现一次&#xff0c;并且按照出现的次数从高到低进行排序&#xff0c;相同出现次数按照第一次出现顺序进行先后排序。 输入描述 一个数组 输出描述 去重排序后的数组…

使用微信怎么图片投票怎么设置qq里面投票是如何

手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。 现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票小程序能够提高工作效率&#xff0c;提高活动的影响力。 那么微信做投票的小程序哪个比较…

苹果头显Vision Pro深度解读2 软件开发者谁最受益?

1 软件开发者谁最受益&#xff1f; 开发Vision pro这种设备的软件啊&#xff0c;首先得跟vision pro本身的特点结合起来&#xff0c;比如它本质上并不是一个很适合移动的的设备。用户大多数时候&#xff0c;都是坐着&#xff0c;站着&#xff0c;躺着使用。 所以典型的应用场…

【Linux】文件描述符与重定向操作

系列文章 收录于【Linux】文件系统 专栏 对于Linux下文件的写入与读取&#xff0c;以及文件原理还有疑惑的可以看看上一篇文章浅谈文件原理与操作。 目录 系列文章 再谈文件描述符 ​编辑 IO函数的本质 一切皆文件 文件重定向 原理 系统接口 再谈文件描述符 &#x…

C语言 指针(特别篇)

本篇目录 C语言 指针&#xff08;特别篇&#xff09;内存地址简要介绍C语言指针C语言的指针可以指向什么?取地址符 &&#xff08;Address-of Operator&#xff09;C语言中的 * 号运算符示例集&#xff1a;指向变量的指针指向数组的指针指向字符串的指针二级指针指针数组的…

doris docker部署 1.2.4.1版本

目录 写在前面 镜像编译 准备工作 下载编译好的包 fe be 编辑初始化文件 fe be 编辑Dockerfile fe be 构建镜像 fe be 构建结果 镜像运行 fe be 修改配置 添加udf依赖 启动be 注册be 错误分析 写在前面 以下操作语句按顺序执行即可&#xff0c;如果需要…