【重温设计模式】访问者模式及其Java示例

访问者模式的基本概念

访问者模式,一种行为型设计模式,其基本定义是:允许一个或者多个操作应用到一组对象上,解耦操作和对象的具体类,使得操作的添加可以独立于对象的类结构变化。在面向对象编程中,访问者模式的重要性不言而喻。它将数据操作和数据结构分离,使得在不改变数据结构的前提下,可以添加新的操作,从而增强了系统的灵活性和可扩展性。

在访问者模式中,数据结构是稳定的,而操作是易变的。这就像一座博物馆,展品(数据结构)是固定的,而参观者(操作)是多变的。

参观者可以根据自己的兴趣和需求,选择不同的参观路径和方式,比如有的人喜欢看古代文物,有的人喜欢看现代艺术,有的人喜欢听讲解,有的人喜欢自己慢慢欣赏。博物馆不需要因为参观者的不同而改变展品的布置,参观者也不需要关心博物馆的内部结构,他们只需要关心自己感兴趣的展品。

public interface Visitor {
    void visit(OneMore oneMore);
}

public class OneMoreMuseum {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

在这个简单的Java代码示例中,OneMoreMuseum是一个元素类,Visitor是访问者接口,visit方法是访问者对OneMoreMuseum元素的操作。OneMoreMuseum元素类有一个accept方法,接受一个访问者对象,然后调用访问者的visit方法,将自身作为参数传入。这样,访问者就可以对OneMoreMuseum元素进行操作了。

接下来,我们将详细解释访问者模式的组成部分,包括访问者、元素、对象结构和具体元素等。

访问者模式的组成部分

在我们理解了访问者模式的基本概念后,接下来我们来详细解析一下访问者模式的组成部分。访问者模式主要由四个部分组成:访问者(Visitor)、元素(Element)、对象结构(ObjectStructure)和具体元素(ConcreteElement)。

首先,访问者(Visitor)是一个接口,它定义了对每一类元素(Element)的访问操作。它的主要任务就是对传入的元素进行一些特定的操作。这些操作依赖于元素的具体类型,同时也依赖于访问者本身的状态。这样,当访问者的状态改变时,它对元素的访问操作也会随之改变。

public interface Visitor {
    void visit(Element element);
}

其次,元素(Element)也是一个接口,它定义了一个accept方法,用于接受访问者对象。当一个元素接受访问者的访问请求时,它把自身作为参数传给访问者的visit方法,让访问者可以对其进行操作。

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

然后,对象结构(ObjectStructure)是一个包含元素集合的类,它提供了一个方法,可以让访问者访问每一个元素。

public class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

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

最后,具体元素(ConcreteElement)是实现元素接口的类,它实现了accept方法,通常情况下,accept方法都是以如下方式实现的:visitor.visit(this)。也就是让访问者访问自己,实现对自己的访问。

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

以上就是访问者模式的主要组成部分。接下来,我们将通过一个具体的Java实例,来进一步深入理解访问者模式的实际应用。

Java中的访问者模式实例

在前面的部分,我们已经介绍了访问者模式的基本概念和组成部分。现在,让我们通过一个Java实例,看看访问者模式在实际应用中的效果。假设我们正在开发一个电子商务项目,我们需要处理多种类型的商品,如书籍、电子设备等。每种商品都有自己的特性,如书籍有作者、出版社、价格等属性,电子设备有品牌、型号、价格等属性。我们需要为这些商品实现一些操作,如打折、免运费等。这就是一个典型的访问者模式的应用场景。

首先,我们定义一个Product接口,代表商品。这个接口有一个accept方法,用来接受访问者的访问。

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

然后,我们定义BookElectronics类,分别代表书籍和电子设备,它们都实现了Product接口。

public class Book implements Product {
    private String author;
    private String publisher;
    private double price;

    // ...省略其他属性和方法...

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

public class Electronics implements Product {
    private String brand;
    private String model;
    private double price;

    // ...省略其他属性和方法...

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

接下来,我们定义一个Visitor接口,代表访问者。这个接口有两个方法,分别用来访问书籍和电子设备。

public interface Visitor {
    void visit(Book book);
    void visit(Electronics electronics);
}

最后,我们定义一个DiscountVisitor类,代表打折的访问者。这个类实现了Visitor接口,实现了对书籍和电子设备打折的操作。

public class DiscountVisitor implements Visitor {
    private static final double BOOK_DISCOUNT = 0.8;
    private static final double ELECTRONICS_DISCOUNT = 0.9;

    @Override
    public void visit(Book book) {
        double newPrice = book.getPrice() * BOOK_DISCOUNT;
        book.setPrice(newPrice);
    }

    @Override
    public void visit(Electronics electronics) {
        double newPrice = electronics.getPrice() * ELECTRONICS_DISCOUNT;
        electronics.setPrice(newPrice);
    }
}

在这个示例中,我们可以看到,访问者模式使得我们可以在不修改商品类的前提下,添加新的操作,如打折。

implements
implements
implements
accepts
1
1
«interface»
Product
+accept(visitor)
Book
-String author
-String publisher
-double price
+accept(visitor)
Electronics
-String brand
-String model
-double price
+accept(visitor)
«interface»
Visitor
+visit(Book book)
+visit(Electronics electronics)
DiscountVisitor
-double BOOK_DISCOUNT
-double ELECTRONICS_DISCOUNT
+visit(Book book)
+visit(Electronics electronics)

这是访问者模式的一大优点。但是,访问者模式也有其缺点,我们将在下一部分进行详细的讨论。

访问者模式的优缺点

现在,我们来讨论的是访问者模式的优缺点。首先,访问者模式的最大优点是它可以使得数据结构和数据操作分离。这意味着,如果你想在不改变数据结构的情况下增加新的操作,访问者模式是一个非常好的选择。例如,

然而,访问者模式也有其缺点。最大的缺点是如果数据结构发生改变,例如增加或删除元素,那么所有的访问者都可能需要修改。这会增加代码的维护难度。此外,访问者模式也破坏了数据结构的封装性,因为访问者需要知道数据结构的内部细节才能进行操作。

总的来说,访问者模式在某些情况下是非常有用的,但在其他情况下可能会带来问题。因此,在决定是否使用访问者模式时,你需要根据你的具体需求来权衡其优缺点。

总结

访问者模式,就像一个开放的博物馆,它接受各种访问者的参观和操作,同时保持自身的稳定和完整。这种模式的灵活性和可扩展性,使得我们可以在不改变数据结构的前提下,添加新的操作,增强了系统的适应性和生命力。

然而,正如同一枚硬币的两面,访问者模式的优点同时也是其缺点。它的开放性可能会破坏数据结构的封装性,使得数据结构的内部细节暴露给访问者,增加了数据的风险。同时,如果数据结构发生改变,所有的访问者都可能需要修改,增加了代码的维护难度。

因此,是否使用访问者模式,需要我们根据实际的需求和条件,进行深思熟虑和权衡。在面对复杂的编程问题时,我们不仅需要掌握各种设计模式,更需要理解和把握它们背后的原理和思想,以便在恰当的时机,选择恰当的工具,解决恰当的问题。

最后,我们希望这篇文章能够帮助你更好地理解和掌握访问者模式,也希望你能够像参观博物馆一样,享受编程的过程,发现编程的美,体验编程的乐趣。

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

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

相关文章

软件推荐 篇三十七:开源免费无广告的在线音乐免费播放 | MusicFree纯净无广告体验-小众冷门推荐

引言 自从QQ音乐没了杰伦、某云开始收费&#xff0c;除了各种广告弹窗导致电脑卡的要死&#xff0c;打工人就靠这点音乐背景熬夜了&#xff0c;木有办法&#xff0c;得有个开源免费的听歌软件吧&#xff0c;一搜github&#xff0c;软件一大堆&#xff0c;作为一个打工仔&#…

八大排序算法之希尔排序

希尔排序是插入排序的进阶版本&#xff0c;他多次调用插入排序&#xff0c;在插入排序上进行了改造&#xff0c;使其处理无序的数据时候更快 核心思想&#xff1a;1.分组 2.直接插入排序&#xff1a;越有序越快 算法思想&#xff1a; 间隔式分组&#xff0c;利用直接插入排序…

java数据结构与算法刷题-----LeetCode215. 数组中的第K个最大元素

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 解题思路&#xff1a;时间复杂度O( n n n)&#xff0c;空间复杂度…

【深度学习】训练Stable Diffusion环境

仓库&#xff1a; https://github.com/bmaltais/kohya_ss.git 基础镜像&#xff1a; from kevinchina/deeplearning:sdxllighting_trt_nginx_002api docker run --net host --gpus device0 -e APIWORKS1 -it t1:t1 bash构建环境&#xff1a; sudo -i git clone https://git…

算法第三十一天-直方图的水量

直方图的水量 题目要求 解题思路 使用面向列的计算比面向行的计算更加容易。我们只需要考虑当前的位置的左右最高模板的高度。 方法一、暴力解法 每个位置能接到多少雨水&#xff0c;很容易想到[木桶效应]&#xff0c;即是由两边最短的木板限制的。那么直观思路就是&#x…

C语言 动态内存管理

目录 前言 一、动态内存分配 二、malloc和free函数 2.1 malloc函数 2.2 free函数 三、calloc和realloc函数 3.1 calloc函数 3.2 realloc函数 四、常见的动态内存的错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用…

深度学习-2.8模型拟合概念和欠拟合模型、过拟合调整策略

模型拟合概念和欠拟合模型、过拟合调整策略 文章目录 模型拟合概念和欠拟合模型、过拟合调整策略一、模型拟合度概念介绍1.测试集的“不可知悖论”2.模型拟合度概念与实验 二、过拟合、欠拟合问题解决方案1. 欠拟合解决方案2.过拟合解决方案 三、神经网络结果选择策略1. 参数和…

拼多多2023年实现营收2476亿 助力品质好物与消费升级双向奔赴

拼多多集团近日发布了截至去年12月31日的财务业绩报告&#xff0c;拼多多在2023年第四季度实现了889亿元的营收&#xff0c;同比增长了惊人的123%。而在全年范围内&#xff0c;拼多多的营收更是高达2476亿元&#xff0c;同比增长了90%。 去年是拼多多全面拥抱高质量发展的元年…

晶体管图示仪 能测 IGBT. Mosfet. Diode. BJT......

STD2000晶体管图示仪系统能测试很多电子元器件的静态直流参数&#xff08;如击穿电压V(BR)CES/V(BR)DSs、漏电流ICEs/lGEs/IGSs/lDSs、阈值电压/VGE(th)、开启电压/VCE(on)、跨导/Gfe/Gfs、压降/Vf、导通内阻Rds(on)&#xff09;。 测试种类覆盖 7 大类别26分类&#xff0c;包…

解锁企业数字化运营管理:论专业数据中台解决方案的重要性-亿发

没有数据中台&#xff0c;数字化经营就像是建立在沙滩上的城堡&#xff0c;缺乏坚实的基础支撑。数据中台对于企业数字化经营能力的建设至关重要&#xff0c;它扮演着连接、整合和管理数据的关键角色&#xff0c;出现将扩展企业可利用数据的范围。传统的业务分析主要使用财务数…

Python使用PaddleOCR进行图片转文字

PaddleOCR是百度飞桨开发的OCR库 安装 安装PaddleOCR&#xff0c;只需要两个命令&#xff1a; pip install paddlepaddle2.4.2 pip install paddleocr 基本使用 PaddleOCR的使用也很简单&#xff1a; from paddleocr import PaddleOCR# use_angle_cls&#xff1a;是否使用…

高通 8255 基本通信(QUP)Android侧控制方法说明

一&#xff1a;整体说明 高通8255芯片中&#xff0c;SPI IIC UART核心统一由QUP V3 进行控制 QUP V3为可编程模块&#xff0c;可以将不同通道配置为SPI IIC UART通路&#xff0c;此部分配置在QNX侧 QUP 资源可以直接被QNX使用&#xff0c;Android侧可以通过两种方法使用QUP资源…

Android Audio相关

AudioManager AudioService的Bp端&#xff0c;调用AudioManager>AudioService&#xff08;代码实现&#xff09; AudioService 继承自IAudioService.Stub&#xff0c;为Bn端 AudioSystem AudioService功能实现都依赖于AudioSystem&#xff0c;AudioService通过AudioSys…

SCXI-1193 控制器 多路复用器开关模块 NI 仪器仪表 SCXI-1001

规范 SCXI -1193 500 MHz四路8x1 50多路复用器 本文件列出了SCXI-1193多路复用器模块的规格。所有规格均为 如有变更&#xff0c;恕不另行通知。请访问ni.com/manuals了解最新规格。 配置四路8x1多路复用器 双通道16x1多路复用器 单路32x1多路复用器 四路4x1端接多路复用器 双路…

Java Swing游戏开发学习15

内容来自RyiSnow视频讲解 这一节讲的是Title Screen&#xff0c;直译&#xff1a;标题屏幕。视频开始没有字幕了&#xff0c;比较考验听力[/doge]&#x1f436;&#xff0c;常听到不认识的单词&#xff0c;一边猜&#xff0c;一边琢磨意思。作者说有许多人讨论如何实现non-gam…

地理数据表达方式学习——KML与SHP

一、KML-Keyhole Markup Language Keyhole Markup Language (KML)是一种XML符号&#xff0c;用于浏览器中二维地图和三维地球的地理注释和地理可视化&#xff08;地理数据包括点、线、面、多边形、多面体以及模型等&#xff09;。KML是伴随着Google Earth的使用而开发的&#x…

ROS机器人入门第一课:ROS快速体验——python实现HelloWorld

文章目录 ROS机器人入门第一课&#xff1a;ROS快速体验——python实现HelloWorld一、HelloWorld实现简介&#xff08;一&#xff09;创建工作空间并初始化&#xff08;二&#xff09;进入 src 创建 ros 包并添加依赖 二、HelloWorld(Python版)&#xff08;二&#xff09;进入 r…

Doris实战——工商信息查询平台的湖仓一体建设

目录 前言 一、架构1.0&#xff1a;传统Lambda架构 二、OLAP引擎调研 三、架构2.0&#xff1a;数据服务层All in Apache Doris 四、架构 3.0&#xff1a;基于Doris Multi-Catalog的湖仓一体架构 五、实践经验 5.1 引入Merge-on-Write&#xff0c;百亿级单表查询提速近三…

好用的客服快捷回复软件推荐

在当今快节奏的商业环境中&#xff0c;客户服务的效率和质量已经成为企业成功的关键因素之一。对于客服工作人员来说&#xff0c;面对海量的客户咨询和问题解答&#xff0c;如何快速而准确地回复&#xff0c;成为了他们日常工作中的一大挑战。选择一款好用的快捷回复工具是非常…

如何做人才运营战略?

招聘人才和人才获取是同义词&#xff0c;但它们并不相同。招聘是大多数雇主的短期解决方案&#xff0c;而人才获取是一个长期解决方案。 企业要想改善企业文化朝着统一的愿景努力&#xff0c;就需要关注长期规划。 人才获取vs人才招聘 招聘是为了填补空缺&#xff0c;人才获取…