【Java 设计模式】行为型之访问者模式
文章目录
- 1. 定义
- 2. 应用场景
- 3. 代码实现
- 结语
访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不改变被访问元素的类的前提下定义对这些元素的新操作。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可以灵活变化而不影响元素的类。在本文中,我们将深入研究Java中访问者模式的定义、结构、使用场景以及如何在实际开发中应用。
1. 定义
访问者模式是一种行为型设计模式,用于在不改变被访问元素的类的前提下定义对这些元素的新操作。访问者模式的核心思想是将数据结构与作用于结构上的操作解耦,使得操作集合可以灵活变化而不影响元素的类。访问者模式通常包含两个主要角色:访问者(Visitor)和具体元素(Concrete Element)。
- 访问者(Visitor): 定义了对具体元素进行访问的接口,每个具体访问者都实现了对应的访问操作
- 具体元素(Concrete Element): 定义了接受访问者的方法,并通过该方法调用访问者的访问操作
2. 应用场景
访问者模式通常在以下场景中使用:
-
数据结构稳定,但对数据结构的操作经常变化:
当数据结构相对稳定,但经常需要变化或增加新的操作时,可以使用访问者模式
-
不同操作涉及不同的元素类型:
当不同的操作需要访问数据结构中不同类型的元素时,可以使用访问者模式
-
避免在元素类中增加新的操作导致类膨胀:
当不希望在元素类中增加新的操作导致类膨胀时,可以使用访问者模式,将操作封装到独立的访问者类中
3. 代码实现
下面通过一个简单的例子来演示访问者模式的实现。假设有一个图形库,我们可以使用访问者模式来实现不同的图形操作。
访问者 - 图形访问者 ShapeVisitor
package com.cheney.demo;interface ShapeVisitor {void visitCircle(Circle circle);void visitRectangle(Rectangle rectangle);
}
具体访问者 - 面积计算访问者 AreaCalculator
package com.cheney.demo;class AreaCalculator implements ShapeVisitor {@Overridepublic void visitCircle(Circle circle) {System.out.println("计算圆的面积");}@Overridepublic void visitRectangle(Rectangle rectangle) {System.out.println("计算矩形的面积");}
}
具体访问者 - 周长计算访问者 PerimeterCalculator
package com.cheney.demo;class PerimeterCalculator implements ShapeVisitor {@Overridepublic void visitCircle(Circle circle) {System.out.println("计算圆的周长");}@Overridepublic void visitRectangle(Rectangle rectangle) {System.out.println("计算矩形的周长");}
}
具体元素 - 圆形 Circle
package com.cheney.demo;class Circle implements Shape {@Overridepublic void accept(ShapeVisitor visitor) {visitor.visitCircle(this);}
}
具体元素 - 矩形 Rectangle
package com.cheney.demo;class Rectangle implements Shape {@Overridepublic void accept(ShapeVisitor visitor) {visitor.visitRectangle(this);}
}
定义具体元素接口 Shape
package com.cheney.demo;interface Shape {void accept(ShapeVisitor visitor);
}
客户端启动器 Main
package com.cheney.demo;public class Main {public static void main(String[] args) {// 使用访问者模式实现不同图形的操作Shape circle = new Circle();Shape rectangle = new Rectangle();ShapeVisitor areaCalculator = new AreaCalculator();ShapeVisitor perimeterCalculator = new PerimeterCalculator();circle.accept(areaCalculator);rectangle.accept(areaCalculator);circle.accept(perimeterCalculator);rectangle.accept(perimeterCalculator);}
}
在上述例子中,ShapeVisitor 是访问者接口,定义了对具体元素进行访问的方法。AreaCalculator 和 PerimeterCalculator 是具体访问者,实现了对应的访问操作。Circle 和 Rectangle 是具体元素,实现了接受访问者的方法,并通过该方法调用访问者的访问操作。Shape 是具体元素接口,规定了元素类需要实现的接口。
在客户端中,我们使用访问者模式实现了不同图形的操作。通过将操作封装到不同的访问者类中,实现了对图形操作和图形元素的解耦。
结语
访问者模式是一种用于在不改变被访问元素的类的前提下定义对这些元素的新操作的设计模式。通过使用访问者模式,可以将操作集合和元素类解耦,提高代码的灵活性和可维护性。在实际开发中,访问者模式常被用于对复杂数据结构进行操作,例如编译器的语法树、文件系统的目录结构等。通过合理使用访问者模式,可以简化操作的添加和维护,提高代码的可扩展性。
【Java 设计模式】系列 《23 种设计模式》 与 《7 大设计原则》 总纲
🚩设计原则
✨单一职责原则(SRP) 规定一个类应该只有一个引起变化的原因
✨开放/封闭原则(OCP) 表明软件实体应该是可以扩展的,但是不可修改的
✨里氏替换原则(LSP) 强调派生类必须能够替代其基类而不引起程序错误
✨依赖倒置原则(DIP) 倡导高层模块不应该依赖于低层模块,二者都应该依赖于抽象
✨接口隔离原则(ISP) 提倡一个类不应该被强迫依赖它不使用的接口
✨合成/聚合复用原则(CARP) 建议尽量使用合成/聚合,尽量不要使用继承
✨迪米特法则(LoD) 规定一个对象应该对其他对象有最少的了解
🚀创建型设计模式
✨单例模式 保证一个类仅有一个实例,并提供一个访问它的全局点
✨工厂方法模式 定义一个用于创建对象的接口,但是由子类决定实例化哪一个类
✨抽象工厂模式 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
✨建造者模式 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
✨原型模式 通过复制现有的对象来创建新对象,而不是从头开始创建
🚀结构型设计模式
✨适配器模式 将一个类的接口转换成客户希望的另外一个接口
✨桥接模式 将抽象部分与它的实现部分分离,使它们都可以独立地变化
✨组合模式 将对象以树形结构组合以表示“部分-整体”的层次结构
✨装饰器模式 动态地给一个对象添加一些额外的职责
✨外观模式 为子系统中的一组接口提供一个一致的界面
✨代理模式 为其他对象提供一种代理以控制对这个对象的访问
✨享元模式 用共享的方式高效地支持大量小粒度对象
🚀行为型设计模式
✨观察者模式 定义对象间的一对多依赖,当一个对象改变状态,所有依赖者都会受到通知并自动更新
✨策略模式 定义一系列算法,将它们封装起来,并且使它们可以相互替换
✨命令模式 将请求封装成对象,使得可以用不同的请求对客户进行参数化
✨状态模式 允许对象在其内部状态改变时改变它的行为
✨责任链模式 为解除请求的发送者和接收者之间的耦合,而使多个对象都有机会处理这个请求
✨访问者模式 将算法与对象结构分离,并且可以在不改变对象结构的前提下定义新的操作
✨中介者模式 用一个中介对象来封装一系列的对象交互
✨备忘录模式 在不破坏封装的情况下,捕获对象的内部状态,并在对象之外保存这个状态
✨迭代器模式 提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示
✨模版方法模式 定义一个操作中的算法的骨架,将一些步骤延迟到子类中
✨解释器模式 定义一个语言的文法,并且建立一个解释器来解释该语言中的句子
相关文章:
【Java 设计模式】行为型之访问者模式
文章目录 1. 定义2. 应用场景3. 代码实现结语 访问者模式(Visitor Pattern)是一种行为型设计模式,用于在不改变被访问元素的类的前提下定义对这些元素的新操作。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可以灵…...
堆和堆排序【数据结构】
目录 一、堆1. 堆的存储定义2. 初始化堆3. 销毁堆4. 堆的插入向上调整算法 5. 堆的删除向下调整算法 6. 获取堆顶数据7. 获取堆的数据个数8. 堆的判空 二、Gif演示三、 堆排序1. 堆排序(1) 建大堆(2) 排序 2.Topk问题 四、完整代码1.堆的代码Heap.cHeap.htest.c 2. 堆排序的代码…...
【全程录屏GPT3.5升级4.0】2024最新GPT4升级订阅详细指南
前言:为什么要升级GPT4.0,下图是来自GPT4.0的官方回答,可以看出,GPT4无愧于是一个大版本升级的。 一、视频教程 记录了普通用户使用WildCrad从GPT3.5升级到4.0的全部过程,感兴趣可以前往观看:https://www.…...
中移(苏州)软件技术有限公司面试问题与解答(4)—— virtio所创建的设备1
接前一篇文章:中移(苏州)软件技术有限公司面试问题与解答(0)—— 面试感悟与问题记录 本文参考以下文章: VirtIO实现原理——PCI基础 VirtIO实现原理——virtblk设备初始化 特此致谢! 本文对…...
《动手学深度学习(PyTorch版)》笔记5
注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过,…...
QT中wchar_t类型如何输出
在Qt中,通常使用QString来处理字符串,而不是wchar_t。QString是Qt中用于处理Unicode字符串的类。如果你有wchar_t类型的字符串,你可以将其转换为QString进行输出。 以下是一个简单的例子: #include <QCoreApplication> #i…...
网络安全04-sql注入靶场第一关
目录 一、环境准备 1.1我们进入第一关也如图: 编辑 二、正式开始第一关讲述 2.1很明显它让我们在标签上输入一个ID,那我们就输入在链接后面加?id1 编辑 2.2链接后面加个单引号()查看返回的内容,127.0.0.1/sqli/less-1/?id1,id1 …...
微服务理解篇
一 :架构演变 1 单体架构: 简单理解为一个服务涵盖所有需求功能2 垂直架构: 按照业务功能将单体架构拆分成小模块服务, 如:订单系统,用户系统,商品系统 ##缺点 引入分布式事务,分布式锁等,优点:模块解耦## 垂直拆分:根据业务层级拆分,比如商城的订单系统,用户系统,商品系统…...
项目篇:基于TCP通信模型的外卖软件实现
一、基本成员及功能实现 本项目主要由服务器,消费者,商家,外卖员组成。基本的功能如下。 对所有人: 1、可以注册登录 2、可以修改个人信息 3、可以销户 商家: 1、注册时需要填写售卖商品信息 2、可以修改商品信…...
深入浅出 diffusion(2):pytorch 实现 diffusion 加噪过程
我在上篇博客深入浅出 diffusion(1):白话 diffusion 原理(无公式)中介绍了 diffusion 的一些基本原理,其中谈到了 diffusion 的加噪过程,本文用pytorch 实现下到底是怎么加噪的。 import torch…...
【软件测试】学习笔记-构建并执行 JMeter 脚本的正确姿势
有些团队在组建之初往往并没有配置性能测试人员,后来随着公司业务体量的上升,开始有了性能测试的需求,很多公司为了节约成本会在业务测试团队里选一些技术能力不错的同学进行性能测试,但这些同学也是摸着石头过河。他们会去网上寻…...
iOS 面试 Swift基础题
一、Swift 存储属性和计算属性比较: 存储型属性:用于存储一个常量或者变量 计算型属性: 计算性属性不直接存储值,而是用 get / set 来取值 和 赋值,可以操作其他属性的变化. 计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体。存储属性可…...
(七)for循环控制
文章目录 用法while的用法for的用法两者之间的联系可以相互等价用for改写while示例for和while的死循环怎么写for循环见怪不怪表达式1省略第一.三个表达式省略(for 改 while)全省略即死循环(上面已介绍) 用法 类比学习while语句 …...
ASP .NET Core Api 使用过滤器
过滤器说明 过滤器与中间件很相似,过滤器(Filters)可在管道(pipeline)特定阶段(particular stage)前后执行操作。可以将过滤器视为拦截器(interceptors)。 过滤器级别范围…...
CodeGPT--(Visual )
GitCode - 开发者的代码家园 gitcode.com/ inscode.csdn.net/liujiaping/java_1706242128563/edit?openFileMain.java&editTypelite marketplace.visualstudio.com/items?itemNameCSDN.csdn-codegpt&spm1018.2226.3001.9836&extra%5Butm_source%5Dvip_chatgpt_c…...
1.Mybatis入门
目录 前言 1入门 1.1 入门程序实现 1.2 数据准备 编辑 1.3 配置Mybatis 1.4 编写SQL语句 1.5 单元测试 1.6 解决SQL警告与提示 2. JDBC介绍(了解) 2.1 介绍 2.2 代码 2.3 问题分析 2.4 技术对比 3. 数据库连接池 3.1 介绍 3.2 产品 4. lombok 4.1 介绍 4.…...
android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式
一、Camera 1.1、结合SurfaceView实现预览 1.1.1、布局 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-au…...
live555搭建流式rtsp服务器
源代码已上传gitee 一、需求 live555源代码中的liveMediaServer是将本地文件作为源文件搭建rtsp服务器,我想用live555封装一个第三方库,接收流数据搭建Rtsp服务器;预想接口如下: class LiveRtspServer { public:/***brief构造一…...
Apache孵化器领路人与导师的职责
对于捐赠到 ASF 孵化器的项目来说, ASF 孵化器项目管理委员会(IPMC)的成员会扮演两个角色,一个 孵化器领路人(Champion),另外一个是孵化器导师(Mentor)。 本文源自 ALC …...
【C++中STL】set/multiset容器
set/multiset容器 Set基本概念set构造和赋值set的大小和交换set的插入和删除set查找和统计 set和multiset的区别pair对组两种创建方式 set容器排序 Set基本概念 所有元素都会在插入时自动被排序。 set/multist容器属于关联式容器,底层结构属于二叉树。 set不允许容…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
