访问者模式:将算法与对象结构分离的设计模式

news2024/9/20 14:45:13

在软件开发中,我们常常需要对对象结构中的各个元素进行不同的操作。比如在编译器中,我们可能需要对抽象语法树(AST)的各个节点进行语法检查、代码生成、优化等操作。如果将这些操作直接嵌入到节点类中,会导致类的职责过多,难以维护。访问者模式通过将操作封装到访问者对象中,使得我们可以在不改变节点类的情况下添加新的操作,从而提高系统的灵活性和可扩展性。

访问者模式是一种行为设计模式,它能将算法与对象结构分离,使得你可以在不改变对象结构的情况下定义新的操作。

一,访问者模式的结构

访问者模式主要包含以下几个角色:

  • Visitor(访问者):为对象结构中的每一个具体元素类声明一个访问操作。
  • ConcreteVisitor(具体访问者):实现每个由 Visitor 声明的操作。
  • Element(元素):定义一个接受访问操作(accept)的接口。
  • ConcreteElement(具体元素):实现接受操作,通常是调用访问者的相应方法。
  • ObjectStructure(对象结构):能枚举它的元素,可以提供一个高层的接口以允许访问者访问它的元素。

uml类图:
在这里插入图片描述

二,访问者模式的实现

下面是一个简单的访问者模式的实现示例:

// 访问者接口
interface Visitor {
    void visit(ElementA elementA);
    void visit(ElementB elementB);
}

// 具体访问者
class ConcreteVisitor implements Visitor {
    public void visit(ElementA elementA) {
        System.out.println("访问 ElementA");
    }

    public void visit(ElementB elementB) {
        System.out.println("访问 ElementB");
    }
}

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素A
class ElementA implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 具体元素B
class ElementB implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 对象结构
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void addElement(Element element) {
        elements.add(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.addElement(new ElementA());
        objectStructure.addElement(new ElementB());

        Visitor visitor = new ConcreteVisitor();
        objectStructure.accept(visitor);
    }
}

三,优缺点

优点:

扩展性好: 可以在不修改对象结构的情况下增加新的操作。
符合单一职责原则: 将不同的操作分离到不同的访问者中。

缺点:

违反了依赖倒置原则: 具体元素依赖访问者接口。
增加新的元素困难: 如果需要增加新的元素,所有的访问者都需要修改。

四,适用场景

对象结构相对稳定,但经常需要在此对象结构上定义新的操作。
需要对一个对象结构中的对象进行很多不同且不相关的操作。

五,总结

访问者模式通过将操作行为从对象结构中分离出来,使得新的操作可以独立于对象结构进行扩展。尽管它在某些情况下会增加系统的复杂性,但在需要频繁扩展操作的场景中,它提供了一种灵活且符合开闭原则的解决方案。


如果你对设计模式、软件架构、编程技巧等内容感兴趣,欢迎关注我们的同名微信公众号【技术拾光者】。在这里,我们将定期分享最新的技术文章和实用的编程技巧,帮助你不断提升自己的技术水平。

扫描下方二维码,立即关注我们吧!
技术拾光者

感谢你的阅读和支持,我们期待与你在微信公众号上交流更多有趣的技术话题!

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

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

相关文章

一、桥式整流电路

桥式整流电路 1、二极管的单向导电性: 伏安特性曲线: 理想开关模型和恒压降模型 2、桥式整流电流流向过程 输入输出波形: 3、计算:Vo,lo,二极管反向电压。 学习心得

数字病理图像处理:分割、合成与数据增强研究|顶刊精析·24-09-20

小罗碎碎念 今日精析&#xff1a;Medical Image Analysis 这篇文章介绍了一种结合了先进分割模型和生成对抗网络的病理切片图像分析流程&#xff0c;用于提高癌症诊断的准确性和效率。 作者角色姓名单位名称&#xff08;中文&#xff09;第一作者Muhammad Jehanzaib博阿齐奇大学…

安卓13修改设置设备型号和设备名称分析与更改-android13设置设备型号和设备名称更改

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 用户要定制一些系统显示的设备型号和设备名称,这就需要我们分析设置里面的相关信息来找到对应的位置进行修改了。 2.问题分析 像这种信息要么是config.xml里面写死了,要…

一、编译原理(引论)

目录 【一】、引论 一、编译器 1、编译器 2、编译器与解释器 3、编译器结构 【一】、引论 一、编译器 1、编译器 &#xff08;1&#xff09;编译器&#xff1a;将人类易懂的 高级语言 翻译成 硬件可执行的目标机器语言 &#xff08;2&#xff09; 高级语言 ⚫ 直接面…

数据结构------二叉树简单介绍及实现

如果不是满二叉树或者完全二叉树&#xff0c;就要用链式存储 //搜索二叉树&#xff1a;左子树的所有值比根小&#xff0c;右子树的所有值比根大 // 实现查找&#xff0c;最多找高度次&#xff08;类似二分法&#xff09; //二分查找存在的问题&#xff1a…

【C++】——多态详解

目录 1、什么是多态&#xff1f; 2、多态的定义及实现 2.1多态的构成条件 ​2.2多态语法细节处理 2.3协变 2.4析构函数的重写 2.5C11 override 和 final关键字 2.6重载—重写—隐藏的对比分析 3、纯虚函数和抽象类 4、多态的原理分析 4.1多态是如何实现的 4.2虚函数…

TESSY创建需要高级桩的测试用例

需要打高级桩的情况如下&#xff1a; 1) 使用到桩函数的返回值&#xff1b; 2) 如果函数有形参&#xff0c;并且需要接口传参检测&#xff1b; 我们以tessy5.1 IDE为例&#xff0c;给大家展示编写一个需要高级桩的测试用例过程。 1、前期的准备工作 可以参考以下文章&…

mac命令行分卷压缩与合并

mac下默认可用命令行分卷压缩 例:一个900k的压缩包名为hello.zip,将其分割为每500K一个zip zip - hello.zip | split -b 500k -a 3 - file.zip.part_ 其他可自定义分割体积,如 -b 10m -b 10g k,m,g无视大小写 打包结果如图所示 分卷合并 #合成一个大文件 cat file.zip.part…

中电信翼康基于Apache Dolphinscheduler重构“星海·济世医疗数据中台”实践经验分享

文章作者&#xff1a;尚志忠 编辑整理&#xff1a;曾辉 行业背景 随着大数据、云计算、5G、人工智能等技术的快速发展&#xff0c;以及医疗信息化建设的不断深入&#xff0c;数据中台作为打通医疗数据融合壁垒、实现数据互通与共享、构建高效数据应用的关键信息平台&#xf…

U 盘显示需要格式化才能用?一针见血的修复方法在这里!速看!

在日常使用电脑的过程中&#xff0c;我们常常会遇到各种让人头疼的问题&#xff0c;其中之一就是当插入 U 盘时&#xff0c;突然弹出提示 “U 盘需要格式化才能使用”。这可让很多人慌了神&#xff0c;毕竟 U 盘里可能存储着重要的文件资料。别着急&#xff0c;下面就为大家介绍…

基于eBPF的procstat软件追踪程序垃圾回收(GC)事件

在性能敏感的应用程序中&#xff0c;偶尔遇到程序无故卡顿是开发者们常见的挑战之一。这种现象可能会表现为突然的延迟、系统响应时间增加、吞吐量的下降。这类问题的根源可能是编程语言的垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;导致&#xff0c;尤…

超易用的AI训练页面!训练推理一体化助你快速炼制AI模型!

模型训练页面展示 AI绘画的热度也不是一天两天了。之前很火的粘土画风转换、AI漫画风格图像等等也都是由AI绘画来实现的。但要想训练一个模型需要很多繁琐的步骤&#xff0c;甚至很多小白都找不到训练模型的资源。 不过现在这个问题已经不需要担心了&#xff0c;厚德云推出了一…

vue websocket 使用

基于webSocket通信的库主要有 socket.io&#xff0c;SockJS 关于SockJS的使用 先安装 sockjs-client 和 stompjs npm install sockjs-client npm install stompjs import SockJS from sockjs-client; import Stomp from stompjs; export default { data () { …

一文看懂Elasticsearch的技术架构:高效、精准的搜索神器

一、概述 Elasticsearch 以其强大的全文本搜索功能而闻名。速度之所以这么快&#xff0c;因为 Elasticsearch 核心采用的是倒排索引&#xff1b;它功能之所以这么强大&#xff0c;是因为采用了可调相关度分数、高级查询 DSL 以及可提升搜索能力的诸多功能。 然而全文本搜索只是…

OpenCV特征检测(4)检测图像中的角点函数cornerHarris()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 Harris 角点检测器。 该函数在图像上运行 Harris 角点检测器。类似于 cornerMinEigenVal 和 cornerEigenValsAndVecs&#xff0c;对于每个像素 (…

LeetCode[中等] 54.螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 思路&#xff1a;定义方向数组&#xff0c;按照顺时针顺序&#xff1a;右(0,1)&#xff0c;下(1,0)&#xff0c;左(0,-1)&#xff0c;上(0,-1) 从矩阵的左上角开始遍历…

卷积参数量计算公式

1. 普通卷积&#xff08;Standard Convolution&#xff09; 普通卷积的参数量计算包括卷积核的权重和可能的偏置项。 2. 深度卷积&#xff08;Depthwise Convolution&#xff09; 深度卷积是逐通道的卷积操作&#xff0c;每个输入通道都有一个独立的卷积核。 3. 逐点卷积&…

骨传导耳机哪个牌子好?盘点口碑最好的5款骨传导耳机!

在快节奏的现代生活中&#xff0c;耳机成为了我们与外界沟通的重要桥梁&#xff0c;无论是在通勤路上、健身锻炼&#xff0c;还是在工作学习中&#xff0c;耳机都扮演着不可或缺的角色。而在众多耳机类型中&#xff0c;骨传导耳机以其独特的声音传导方式和健康舒适的佩戴体验&a…

C语言中的assert断言

Assert断言 断言是程序中处理异常的一种高级形式。可以在任何时候启用和禁用断言验证&#xff0c;因此可以在测试时启用断言&#xff0c;而在部署时禁用断言。同样&#xff0c;程序投入运行后&#xff0c;最终用户在遇到问题时可以重新启用断言。 用法&#xff1a; #…

Qt窗口——QDockWidget

文章目录 浮动窗口浮动窗口使用示例 浮动窗口 QDockWidget浮动窗口可以认为是子窗口&#xff0c;每一个子窗口都可以停靠在四周&#xff0c;像Qt Creator页面&#xff0c;就很多的子窗口&#xff1a; 浮动窗口使用示例 创建&#xff1a; QDockWidget* dockWidget new QDock…