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

news2024/9/22 1:08:48

访问者模式的基本概念

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

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

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

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)

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

访问者模式的优缺点

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

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

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

总结

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

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

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

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

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

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

相关文章

sqllab第35-45关通关笔记

35关知识点&#xff1a; 宽字节注入数值型注入错误注入 payload:id1andextractvalue(1,concat(0x7e,database(),0x7e))0--联合注入 payload:id0unionselect1,database(),version()-- 36关知识点&#xff1a; 字符型注入宽字节注入错误注入 payload:id1%df%27andextractvalue(…

什么是浏览器指纹识别?Maskfog指纹浏览器有用吗?

浏览器指纹识别是好是坏&#xff1f;这现在确实是一个有争议的话题。83%的消费者经常或偶尔会根据浏览历史记录看到广告。其实这就是利用了浏览器指纹技术。 如果您想了解浏览器指纹识别是什么&#xff0c;那就看下去&#xff01; 一、什么是浏览器指纹识别 浏览器指纹是指无…

Linux学习之自定义协议

前言&#xff1a; 首先对于Tcp的socket的通信&#xff0c;我们已经大概了解了&#xff0c;但是其中其实是由一个小问题&#xff0c;我们目前是不得而知得&#xff0c;在我们客户端与服务端连接成功后&#xff0c;服务端读取来自客户端得消息&#xff0c;我们使用的是函数read,…

线程池相关详解

1.线程池的核心参数 线程池核心参数主要参考ThreadPoolExecutor这个类的7个参数的构造函数&#xff1a; corePoolSize核心线程数目 maximumPoolSize最大线程数目&#xff08;核心线程救急线程的最大数目&#xff09; keepAliveTime生存时间:救急线程的生存时间&#xff0c;生…

Pytorch入门实战 P3-天气识别

目录 一、前期准备 1、查看设备 2、导入本地数据 3、测试下获取到的天气数据 4、图像预处理 5、划分数据集 6、加载数据集 二、搭建简单的CNN网络&#xff08;特征提取分类&#xff09; 三、训练模型 1、设置超参数 2、编写训练函数 3、编写测试函数 4、正式训练 …

4、类加载器

2.4.1 什么是类加载器 类加载器&#xff08;ClassLoader&#xff09;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术&#xff0c;类加载器只参与加载过程中的字节码获取并加载到内存这一部分。 类加载器会通过二进制流的方式获取到字节码文件的内容&#xff0c…

Visual Studio配置libtorch(cuda安装一步到位)

Visual Studio配置libtorch visual Studio安装cuDNN安装CUDAToolkit安装libtorch下载Visual Studio配置libtorch(cuda版本配置) visual Studio安装 visual Studio点击安装 具体的安装和配置过程这里就不进行细讲了&#xff0c;可以参考我这篇博客Visual Studio配置OpenCV(保姆…

【嵌入式学习】Qtday03.21

一、思维导图 二、练习 自由发挥登录窗口的应用场景&#xff0c;实现一个登录窗口界面。&#xff08;不要使用课堂上的图片和代码&#xff0c;自己发挥&#xff0c;有利于后面项目的完成&#xff09; 要求&#xff1a; 1. 需要使用Ui界面文件进行界面设计 2. ui界面上的组件…

vue.js制作学习计划表案例

通俗易懂&#xff0c;完成“学习计划表”用于对学习计划进行管理&#xff0c;包括对学习计划进行添加、删除、修改等操作。 一. 初始页面效果展示 二.添加学习计划页面效果展示 三.修改学习计划完成状态的页面效果展示 四.删除学习计划 当学习计划处于“已完成”状态时&…

栈——数据结构——day4

栈的定义 栈是限定仅在一段进行插入和删除操作的线性表。 我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表&#xff0c;简称LIFO结构。 栈的插入操作&#xff0c;叫作进栈&#…

开源项目ChatGPT-Next-Web的容器化部署(三)-- k8s deployment.yaml部署

一、说在前面的话 有了docker镜像&#xff0c;要把一个项目部署到K8S里&#xff0c;主要就是编写deployment.yaml。 你需要考虑的是&#xff1a; 环境变量服务的健康检测持久化启动命令程序使用的数据源程序使用的配置文件 因为本前端项目比较简单&#xff0c;这里只做一个…

重学SpringBoot3-Profiles介绍

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Profiles介绍 Profiles简介如何在Spring Boot中使用Profiles定义Profiles激活ProfilesIDEA设置active profile使用Profile-specific配置文件 条件化Bean…

Python爬虫案例-爬取主题图片(可以选择自己喜欢的主题)

2024年了&#xff0c;你需要网络资源不能还自己再慢慢找吧&#xff1f; 跟着博主一块学习如何利用爬虫获取资源&#xff0c;从茫茫大海中寻找那个她到再妹子群中找妹子&#xff0c;闭着眼睛都可以找到合适的那种。文章有完整示例代码&#xff0c;拿过来就可以用&#xff0c;欢迎…

就业班 第二阶段 2401--3.18 day1 初识mysql

初识&#xff1a; 1、关系型数据库mysql、mariadb、sqlite 二维关系模型 2、非关系型数据库 redis、memcached sql 四个部分 DDL 数据库定义语言 创建数据库&#xff0c;创建用户&#xff0c;创建表 DML 数据库操作语言 增删改 DQL 数据库查询语言 查 DCL 数据库控制语言 授权 …

Pake一键打包,轻松构建桌面级应用!

Pake&#xff1a;顷刻之间&#xff0c;智能封装——WEB到桌面瞬间联通&#xff0c;让网站应用像搭积木般部署 - 精选真开源&#xff0c;释放新价值。 概览 Pake&#xff0c;作为一款新颖且极具创新性的桌面应用开发框架&#xff0c;凭借其独特的技术路径和高效的实现方式&…

时代教育期刊投稿发表

《时代教育》是由成都传媒集团主管主办&#xff0c;中华人民共和国新闻出版总署批准国内公开出版发行的专业教育类期刊&#xff0c;主要刊登各类高等院校、职业技术学校、中小学教师及研究生、教育科研工作者的教育实践研究成果&#xff1b;教育教学行业的最新动态&#xff1b;…

基于SSM+Jsp+Mysql的KTV点歌系统

基于SSMJspMysql的KTV点歌系统 基于SSMJspMysql的KTV点歌系统的设计与实现 开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工…

jvm提供的远程调试 简单使用

JVM自带远程调试功能 JVM远程调试&#xff0c;其实是两个虚拟机之间&#xff0c;通过socket通信&#xff0c;达到远程调试的目的&#xff1b; 前提 确保本地和远程的网络是开通的&#xff1b; 本地操作 远程操作 在启动命令参数中 把上面的内容复制进去

第 6 章 ROS-URDF练习(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 6.3.4 URDF练习 需求描述: 创建一个四轮圆柱状机器人模型&#xff0c;机器人参数如下&#xff0c;底盘为圆柱…

NIVision-相机图像采集

应用场景 上位机与工业相机通讯&#xff0c;控制相机抓取图像。 工业相机的通讯接口大多为USB口或网口。 USB口则直接将通讯线缆插入上位机USB端口&#xff0c;打开MAX中设备与接口一栏可以看到电脑给相机分配的资源名称&#xff1b;网口则需要将网线连接相机和上位机&#xf…