设计模式1-访问者模式

访问者模式是一种行为设计模式,它允许你定义在对象结构中的元素上进行操作的新操作,而无需修改这些元素的类。这种模式的主要思想是将算法元素的结构分离开,使得可以在不修改元素结构的情况下定义新的操作。

所谓算法与元素结构分离,即保持元素(被访问对象)结构的稳定,而将算法置于访问者之中,因为访问者可以新建,这样就符合了OCP(开闭原则)。

在访问者模式中,有两个主要的角色:

  1. 访问者(Visitor)
    定义了在对象结构中访问元素时的新操作接口。通常会有多个不同的访问者,每个访问者实现一组特定的操作。

  2. 元素(Element)
    定义了接受访问者的接口,通常会有多个不同的元素,每个元素实现了接口并提供了接受访问者的方法。

访问者模式的主要优势在于当需要在一组对象上执行一些复杂的操作时,你可以通过添加新的访问者而不是修改每个元素的类来扩展系统。

类图:

 

时序图:

 

下面是一个简单的 Java 示例,演示了访问者模式的基本结构:

// 访问者接口
interface Visitor {void visit(ElementA elementA);void visit(ElementB elementB);
}// 元素接口
interface Element {void accept(Visitor visitor);
}// 具体的元素A
class ElementA implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}// 元素A的特定操作void operationA() {System.out.println("Performing operation A on ElementA");}
}// 具体的元素B
class ElementB implements Element {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}// 元素B的特定操作void operationB() {System.out.println("Performing operation B on ElementB");}
}// 具体的访问者
class ConcreteVisitor implements Visitor {@Overridepublic void visit(ElementA elementA) {elementA.operationA();}@Overridepublic void visit(ElementB elementB) {elementB.operationB();}
}// 客户端代码
public class VisitorPatternExample {public static void main(String[] args) {Element elementA = new ElementA();Element elementB = new ElementB();Visitor visitor = new ConcreteVisitor();elementA.accept(visitor); // 执行 ElementA 的操作elementB.accept(visitor); // 执行 ElementB 的操作}
}

在这个例子中,Visitor 接口定义了两个访问方法,每个方法对应一个具体的元素。Element 接口定义了接受访问者的方法。具体的元素类 ElementAElementB 实现了 Element 接口,并分别实现了自己的特定操作。ConcreteVisitor 是一个具体的访问者类,实现了对每个元素的访问操作。

在客户端代码中,我们创建了一个 ConcreteVisitor 实例,并让每个元素接受这个访问者。换言之,是在Client中操作了访问者与元素的连接印证了类图。这样,通过不同的访问者,我们可以执行不同的操作,而不需要修改元素的类。这是访问者模式的一种简单示例,实际中可能涉及更复杂的场景和多个元素。

怎么定义新的操作?

当使用访问者模式时,定义新的操作就是创建新的实现了访问者接口的具体访问者类。每个具体访问者类负责实现一组特定的操作,而这些操作可以是全新的、与原有操作不相关的,或者是对现有操作的扩展。

举个例子,假设我们有一个图形结构,包括圆形(Circle)和矩形(Rectangle)两种图形。现在我们希望实现两种不同的操作:计算图形的面积和计算图形的周长。

首先,定义图形接口和具体的图形类:

// 图形接口
interface Shape {void accept(Visitor visitor);
}// 圆形类
class Circle implements Shape {private double radius;public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}// 矩形类
class Rectangle implements Shape {private double width;private double height;public Rectangle(double width, double height) {this.width = width;this.height = height;}public double getWidth() {return width;}public double getHeight() {return height;}@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}
}

然后,定义访问者接口和具体的访问者类:

// 访问者接口
interface Visitor {void visit(Circle circle);void visit(Rectangle rectangle);
}// 计算面积的具体访问者类
class AreaCalculator implements Visitor {@Overridepublic void visit(Circle circle) {double area = Math.PI * circle.getRadius() * circle.getRadius();System.out.println("Area of Circle: " + area);}@Overridepublic void visit(Rectangle rectangle) {double area = rectangle.getWidth() * rectangle.getHeight();System.out.println("Area of Rectangle: " + area);}
}// 计算周长的具体访问者类
class PerimeterCalculator implements Visitor {@Overridepublic void visit(Circle circle) {double perimeter = 2 * Math.PI * circle.getRadius();System.out.println("Perimeter of Circle: " + perimeter);}@Overridepublic void visit(Rectangle rectangle) {double perimeter = 2 * (rectangle.getWidth() + rectangle.getHeight());System.out.println("Perimeter of Rectangle: " + perimeter);}
}

现在我们可以在不修改图形类的情况下定义新的操作。例如,创建了两个具体的访问者类 AreaCalculatorPerimeterCalculator 分别用于计算图形的面积和周长。在客户端代码中,我们可以通过接受不同的访问者来执行不同的操作:

public class VisitorExample {public static void main(String[] args) {Shape circle = new Circle(5);Shape rectangle = new Rectangle(4, 6);Visitor areaCalculator = new AreaCalculator();Visitor perimeterCalculator = new PerimeterCalculator();circle.accept(areaCalculator); // 计算圆形的面积circle.accept(perimeterCalculator); // 计算圆形的周长rectangle.accept(areaCalculator); // 计算矩形的面积rectangle.accept(perimeterCalculator); // 计算矩形的周长}
}

这样,通过定义不同的访问者,我们可以轻松地扩展系统,而无需修改图形类的结构。

结论:

访问者模式很好地实现了访问算法开放被访问元素封闭,有这种需求时就可以考虑使用访问者模式。

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

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

相关文章

###C语言程序设计-----C语言学习(9)#函数基础

前言:感谢您的关注哦,我会持续更新编程相关知识,愿您在这里有所收获。如果有任何问题,欢迎沟通交流!期待与您在学习编程的道路上共同进步。 一. 基础知识的学习 1.函数的定义 函数是一个完成特定工作的独立程序模块&…

JavaWeb之HTML-CSS --黑马笔记

什么是HTML ? 标记语言:由标签构成的语言。 注意:HTML标签都是预定义好的,HTML代码直接在浏览器中运行,HTML标签由浏览器解析。 什么是CSS ? 开发工具 VS Code --安装文档和安装包都在网盘中 链接:https://p…

2024年混合云:趋势和预测

混合云环境对于 DevOps 团队变得越来越重要,主要是因为它们能够弥合公共云资源的快速部署与私有云基础设施的安全和控制之间的差距。这种环境的混合为 DevOps 团队提供了灵活性和可扩展性,这对于大型企业中的持续集成和持续部署 (CI/CD) 至关重要。 在混…

uniapp踩坑之项目:简易版不同角色显示不一样的tabbar和页面

1. pages下创建三个不同用户身份的“我的”页面。 显示第几个tabbar,0是管理员 1是财务 2是司机 2. 在uni_modules文件夹创建底部导航cc-myTabbar文件夹,在cc-myTabbar文件夹创建components文件夹,在components文件夹创建cc-myTabbar.vue组件…

Java 正则匹配sql

文章目录 正则匹配sql表名称insert intoupdate 正则表达式什么时候要加^$ 在线正则校验 正则匹配sql表名称 insert into insert into PING_TABLE (CODE, NAME) VALUES(0, 待提交),(1, 审核中),(2, 审核通过),(3, 已驳回); regex -> insert\sinto\s(\w)\s*\(?update upda…

Qt 范例阅读: QStateMachine状态机框架 和 SCXML 引擎简单记录(方便后续有需求能想到这两个东西)

一、QStateMachine 简单应用: 实现按钮的文本切换 QStateMachine machine; //定义状态机(头文件定义)QState *off new QState(); //添加off 状态off->assignProperty(ui->pushButton_2, "text", "Off"); //绑定该…

idea修改项目git地址

大家好,今天给大家分享的知识是如何在idea中修改项目的git地址。 一、修改地址 首先我们先找到菜单栏中Git选项,然后点击管理远程(Manage Remote) 之后双击origin之后就可以定义名称或者URL了。

wangEditor v4的简单使用

当前文档是 wangEditor v4 版本的。 wangEditor v5 已经正式发布,可参考文档。 v5 发布之后,v4 将不再开发新功能。 介绍 English documentation wangEditor4 —— 轻量级 web 富文本编辑器,配置方便,使用简单。 官网&#…

基于SpringBoot的后端导出Excel文件

后端导出Excel,前端下载。 系列文章指路👉 系列文章-基于SpringBoot3创建项目并配置常用的工具和一些常用的类 文章目录 后端导出Excel引入依赖写入响应 前端下载后端导出失败和成功返回的内容类型不同,因此需要分别判断。 工具类ServletUti…

基于springboot智慧养老平台源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

第97讲:MHA高可用集群模拟主库故障以及修复过程

文章目录 1.分析主库故障后哪一个从库会切换为主库2.模拟主库故障观察剩余从库的状态2.1.模拟主库故障2.3.当前主从架构 3.修复故障的主库3.1.修复主库3.2.当前主从架构3.3.恢复MHA 1.分析主库故障后哪一个从库会切换为主库 在模拟MHA高可用集群主库故障之前,我们先…

全面解析:船运物流管理系统背后的技术

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

ensp实验合集(二)

实验6 VLAN划分....................................................................... - 30 - 实验7 路由器调试及常用命令使用........................................ - 42 - 实验8 配置静态路由器............................................................…

Modbus协议学习第七篇之libmodbus库API介绍(modbus_write_bits等)

写在前面 在第六篇中我们介绍了基于libmodbus库的演示代码,那本篇博客就详细介绍一下第六篇的代码中使用的基于该库的API函数。另各位读者,Modbus相关知识受众较少,如果觉得我的专栏文章有帮助,请一定点个赞,在此跪谢&…

2024美赛数学建模A题思路分析 - 资源可用性和性别比例(2)

# 1 赛题 问题A:资源可用性和性别比例 虽然一些动物物种存在于通常的雄性或雌性性别之外,但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1:1,但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。…

HSM加密机原理:密钥管理和加密操作从软件层面转移到物理设备中 DUKPT 安全行业基础8

HSM加密机原理 硬件安全模块(HSM)是一种物理设备,设计用于安全地管理、处理和存储加密密钥和数字证书。HSM广泛应用于需要高安全性的场景,如金融服务、数据保护、企业安全以及政府和军事领域。HSM提供了一种比软件存储密钥更安全…

python算法与数据结构---动态规划

动态规划 记不住过去的人,注定要重蹈覆辙。 定义 对于一个模型为n的问题,将其分解为k个规模较小的子问题(阶段),按顺序求解子问题,前一子问题的解,为后一子问题提供有用的信息。在求解任一子…

无向图-树的重心-DFS求解

思路: 本题的本质是树的dfs, 每次dfs可以确定以u为重心的最大连通块的节点数,并且更新一下ans。 也就是说,dfs并不直接返回答案,而是在每次更新中迭代一次答案。 这样的套路会经常用到,在 树的dfs 题目中…

yarn/npm certificate has expired

目录 报错 原因:HTTPS 证书验证失败 方法 a.检查网络安全软件:可能会拦截或修改 HTTPS 流量 b.strict-ssl:false关闭验证【临时方法】 报错 info No lockfile found. [1/4] Resolving packages... error Error: certificate has expired at TLS…

如何发布自己的npm包:

1.创建一个打包组件或者库: 安装weback: 打开项目: 创建webpack.config.js,创建src目录 打包好了后发现两个js文件都被压缩了,我们想开发使用未压缩,生产使用压缩文件。 erserPlugin:(推荐使用…