设计模式(行为型设计模式——访问者模式)

设计模式(行为型设计模式——访问者模式)

访问者模式

基本定义

将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。

模式结构

  • Vistor 抽象访问者:为该对象结构中的ConcreteElement的每一个类声明的一个操作。
  • ConcreteVisitor 具体访问者:实现Visitor申明的每一个操作,每一个操作实现算法的一部分。
  • Element 抽象元素:定义一个Accept操作,它以一个访问者为参数。
  • ConcreteElement 具体元素 :实现Accept操作。
  • ObjectStructure 对象结构:能够枚举它的元素,可以提供一个高层的接口来允许访问者访问它的元素。

代码实现

Vistor 抽象访问者
/*** @Description 抽象访问者 Vistor* vistor中方法的个数,直接对应元素具体类的子数**/
public interface Vistor {//支出账单void view(ExpenseBillElement expenseBillElement);//收入账单void view(IncomeBillElement incomeBillElement);
}
ConcreteVisitor 具体访问者
//访问者BOSS:查看收入和支出总和
@Slf4j
public class BossVistor implements Vistor {double totalExpenses;//总支出double totalIncome;//总收入public double getTotalExpenses() {log.info("老板查看总支出: {} RMB", this.totalExpenses);return totalExpenses;}public double getTotalIncome() {log.info("老板查看总收入: {} RMB", this.totalIncome);return totalIncome;}/*** 查看支出* @param expenseBillElement*/@Overridepublic void view(ExpenseBillElement expenseBillElement) {totalExpenses += expenseBillElement.getAmount();}/*** 查看收入* @param incomeBillElement*/@Overridepublic void view(IncomeBillElement incomeBillElement) {totalIncome += incomeBillElement.getAmount();}
}
//访问者财务人员:查看每一笔收入详情
@Slf4j
public class FinanceVistor implements Vistor {@Overridepublic void view(ExpenseBillElement expenseBillElement) {log.info("财务查看支出栏目 :{} , 支出金额:{}", expenseBillElement.getItem(), expenseBillElement.getAmount());}@Overridepublic void view(IncomeBillElement incomeBillElement) {log.info("财务查看收入栏目 :{} , 支出金额:{}", incomeBillElement.getItem(), incomeBillElement.getAmount());}
}
Element 抽象元素
/**
* 账单
* 提供接受访问的方法
**/
public interface BillElement {void accept(Vistor vistor);
}
ConcreteElement 具体元素
//支付账单元素
public class ExpenseBillElement implements BillElement {double amount;String item;public double getAmount() {return amount;}public void setAmount(double amount) {this.amount = amount;}public String getItem() {return item;}public void setItem(String item) {this.item = item;}public ExpenseBillElement(double amount, String item) {this.amount = amount;this.item = item;}@Overridepublic void accept(Vistor vistor) {vistor.view(this);}
}//收入账单元素
public class IncomeBillElement implements BillElement {double amount;String item;public double getAmount() {return amount;}public String getItem() {return item;}public IncomeBillElement(double amount, String item) {this.amount = amount;this.item = item;}@Overridepublic void accept(Vistor vistor) {vistor.view(this);}
}
ObjectStructure 对象结构
public class BillBook {private List<BillElement> billElementList = new ArrayList<>();public void addBill(BillElement billElement){billElementList.add(billElement);}/**** 1、所有访问者都是通过show方法进行最终访问,也就是说谁要访问对象,*      都要经过show方法,将访问者传入show方法** 2、通过账单循环迭代,可以将所有元素一一列举,*    如果对于一些访问者的目的, 可以通过自己的类,对元素进行检索** @param vistor*/public void show(Vistor vistor){billElementList.stream().forEach(billElement -> {billElement.accept(vistor);});}
}
测试类
public class Test {public static void main(String[] args) {BillBook billBook = new BillBook();billBook.addBill(new ExpenseBillElement(1000d, "工资"));billBook.addBill(new ExpenseBillElement(2000d, "买材料"));billBook.addBill(new IncomeBillElement(3000d, "卖产品"));billBook.addBill(new IncomeBillElement(1000d, "做广告"));BossVistor bossVistor = new BossVistor();billBook.show(bossVistor);bossVistor.getTotalExpenses();bossVistor.getTotalIncome();FinanceVistor financeVistor = new FinanceVistor();billBook.show(financeVistor);}
}
执行结果:

BossVistor - 老板查看总支出: 3000.0 RMB

BossVistor - 老板查看总收入: 4000.0 RMB

FinanceVistor - 财务查看支出栏目 :工资 , 支出金额:1000.0

FinanceVistor - 财务查看支出栏目 :买材料 , 支出金额:2000.0

FinanceVistor - 财务查看收入栏目 :卖产品 , 支出金额:3000.0

FinanceVistor - 财务查看收入栏目 :做广告 , 支出金额:1000.0

优点

  • 高扩展。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。

  • 高复用。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。

  • 松耦合。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。

  • 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

缺点

  • 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。

  • 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。

  • 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。

使用场景

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

总结

  • 访问者模式封装了对象结构元素之上的操作,使得新增元素的操作变得非常简单。所以它比较适用于那么对象结构很少变化的类。
  • 访问者模式中对象结构存储了不同类型的元素对象,以供不同访问者访问。

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

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

相关文章

ALPHA开发板修改CAN的设备树节点信息

一. 简介 上一篇文章通过查看 CAN硬件原理图知道了 CAN1接口对应的IO。文章地址如下&#xff1a; ALPHA开发板中CAN硬件图-CSDN博客 通过ALPHA开发板上的 CAN接口的硬件原理图知道&#xff0c;CAN1_TX 和 CAN1_RX 是 I.MX6ULL的 FlexCAN1 的发送和接收引脚&#xff0c;分别对…

Eureka和Nacos的关系

目录 它们的比较&#xff1a; 结论&#xff1a; Eureka和Nacos都是服务发现和注册中心&#xff0c;它们在微服务架构中扮演着关键角色&#xff0c;但它们是由不同的组织开发的&#xff0c;服务于类似但不完全相同的目的。以下是它们之间的关系&#xff1a; Eureka&#xff1a…

JDK下载配置

一、JDK的作用 Java开发环境&#xff1a;JDK提供了完整的Java开发环境&#xff0c;包含编译器&#xff08;javac&#xff09;、解释器&#xff08;java&#xff09;、打包工具&#xff08;jar&#xff09;、文档生成工具&#xff08;javadoc&#xff09;等一系列工具&#xff0…

SpringBoot健康监控

文章目录 1-SpringBoot2-监控-健康监控服务2-SpringBoot2-监控-Admin可视化 在Spring Boot中&#xff0c;可以通过Actuator模块实现应用程序的健康监控。Actuator是Spring Boot提供的一个用于监控和管理应用程序的模块&#xff0c;可以轻松地查看应用程序的运行状况、性能指标和…

Python3条件控制实战

在Python编程中,条件控制是一种重要的编程概念,它允许我们根据条件的成立与否来执行不同的代码块。在本文中,我们将探讨Python3中条件控制的实际运用,并通过示例来演示其用法。 什么是条件控制? 条件控制是编程中的一种结构,它允许根据条件的真假来选择执行不同的代码路…

有什么可以下载网页视频的浏览器插件 浏览器如何下载网页视频 网页视频怎么下载到本地 网页视频下载软件 IDM下载

在视频网站上看电影追剧&#xff0c;已经成为了大众生活中必不可少的一部分。为了保护自家视频的版权&#xff0c;很多平台都禁止用户下载会员视频。其实只要掌握了正确的方法&#xff0c;一样可以将会员视频下载到本地保存。那么有关有什么可以下载网页视频的浏览器&#xff0…

Websocket + Vue使用

这里有一篇文档可以参考一下> 闪现 POM文件 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.0</version> </dependency> WebSocketConf…

数据库之MongoDB应用与开发

MongoDB应用与开发 1. MongoDB安装 l 官网下载安装介质&#xff1a; Try MongoDB Atlas Products | MongoDB 选择对应版本 修改环境变量 vi /etc/profile export MONGODB_HOME/home/lijin/mongodb export PATH P A T H : PATH: PATH:MONGODB_HOME/bin source /etc/profile …

TnT-LLM: Text Mining at Scale with Large Language Models

TnT-LLM: Text Mining at Scale with Large Language Models 相关链接&#xff1a;arxiv 关键字&#xff1a;Large Language Models (LLMs)、Text Mining、Label Taxonomy、Text Classification、Prompt-based Interface 摘要 文本挖掘是将非结构化文本转换为结构化和有意义的…

矩阵计算-线性系统和 LU 分解

一、三角系统 …… 二、高斯消元法 …… 三、LU分解--直接三角分解法 求解线性方程Axb&#xff1a; 参考视频&#xff1a;【数值分析】矩阵LU三角分解| 速成讲解 考试宝典_哔哩哔哩_bilibili 令ALU&#xff0c;其中L是单位下三角矩阵&#xff08;对角线上元素都是1&#xff…

【python】(08)理解Python中的可变对象和不可变对象

系列文章回顾 【python】(01)初识装饰器Decorator 【python】(02)初识迭代器Iterator 【python】(03)初识生成器Generator 【python】(04)python中实现多任务并发和并行的区别 【python】(05)如何python中的logging模块记录日志信息 【python】(06)理解Python中的 lambda 、map…

golang 轻量数据库推荐

在Go语言&#xff08;Golang&#xff09;生态系统中&#xff0c;有许多轻量级的数据库选项可供选择&#xff0c;这些数据库特别适合用于小型项目、微服务架构或者需要高性能和快速响应的场景。以下是一些推荐的轻量级数据库和库&#xff1a; jmoiron/sqlx: 这是一个轻量级的SQL…

精神暴力的来源与解药

导致人生病的&#xff0c;不仅是病毒或细菌&#xff0c;也有精神暴力。与病毒破坏物理肌体、摧毁生命不同&#xff0c;精神暴力是让人们在过度的自我狂热中燃尽自我、而毁灭自身的。 21世纪以来&#xff0c;精神方面的疾病越来越多&#xff0c;为什么这样呢&#xff1f;大的背景…

git基础-查看提交历史

查看提交历史 在创建了多个提交之后&#xff0c;或者如果克隆了一个具有现有提交历史的存储库&#xff0c;可能会想要回顾一下发生了什么。最基本和强大的工具就是 git log 命令。 运行下git log查看下输出状态 默认情况下&#xff0c;不带任何参数运行 git log 命令会以逆时…

【工具】cassetteai — 制作音乐就像现在写提示一样简单

Cassette 是一种人工智能驱动的音乐创作工具,使各种技能水平的用户都可以根据自己的特定需求和偏好生成高质量、免版税的音乐曲目。它基于基于潜在扩散 (LDM) 的机器学习模型,可以使用用户提供的文本描述来想象节拍。它具有易于使用的界面,用户可以输入各种参数,例如所需的…

AGV|机器人导航识别二维码视觉传感器TDCS-0100与上位机PLC联机实例说明

目前二维码视觉导航的AGV出货量非常大&#xff0c;几乎都是仓储型AGV使用的导航方式。在地面或者天花板等位置标贴二维码作为标记点&#xff0c;通过扫描读取二维码信息和二维码相对相机的角度来确定当前位置。 本文重点介绍AGV|机器人导航识别二维码视觉传感器TDCS-0100与上位…

unity学习(68)——相机/模型的旋转/位置计算

这个比想象中要难&#xff0c;而且需要自己写。 1.相机可以转xy两个位置&#xff0c;可以点头和转圈。注意这里有一个if判断&#xff08;后面返回来发现了这些问题&#xff09; 2.角色不能点头&#xff0c;只能转圈。 难得是移动方向&#xff0c;因为移动方向(位置)和转向是相…

在Sequence中缓存Niagara粒子轨道

当Sequence中粒子特效较多时&#xff0c;播放检查起来较为麻烦&#xff0c;而使用Niagara缓存功能可将粒子特效方便的缓存起来&#xff0c;并且还可以更改播放速度与正反播放方向&#xff0c;便于修改。 1.使用Niagara缓存需要先在插件里打开NiagaraSimCaching 2.创建一个常…

web前端之行为验证码、不同设备和屏幕尺寸呈现不同大小、元素宽度根据视口宽度进行调整、元素或图片裁剪、图片验证码

MENU 前言版本一(htmlJScss)版本二(htmlJScsscanvas) 前言 1、版本一的样式比较齐全&#xff1b; 2、版本二的JS逻辑和功能效果比较完善&#xff0c;且是别人的代码&#xff0c;后续会对样式进行完善。[Gitee | 哔哩哔哩]&#xff1b; 3、两个版本各有千秋&#xff0c;主要学习…

Kafka系列之:Connect 中的错误报告

Kafka系列之:Connect 中的错误报告 Kafka Connect 提供错误报告来处理各个处理阶段遇到的错误。默认情况下,转换期间或转换中遇到的任何错误都会导致连接器失败。每个连接器配置还可以通过跳过此类错误、选择性地将每个错误以及失败操作的详细信息和有问题的记录(具有各种详…