当前位置: 首页 > news >正文

【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 是访问者接口,定义了对具体元素进行访问的方法。AreaCalculatorPerimeterCalculator 是具体访问者,实现了对应的访问操作。CircleRectangle 是具体元素,实现了接受访问者的方法,并通过该方法调用访问者的访问操作。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中&#xff0c;通常使用QString来处理字符串&#xff0c;而不是wchar_t。QString是Qt中用于处理Unicode字符串的类。如果你有wchar_t类型的字符串&#xff0c;你可以将其转换为QString进行输出。 以下是一个简单的例子&#xff1a; #include <QCoreApplication> #i…...

网络安全04-sql注入靶场第一关

目录 一、环境准备 1.1我们进入第一关也如图&#xff1a; ​编辑 二、正式开始第一关讲述 2.1很明显它让我们在标签上输入一个ID&#xff0c;那我们就输入在链接后面加?id1 ​编辑 2.2链接后面加个单引号()查看返回的内容&#xff0c;127.0.0.1/sqli/less-1/?id1,id1 …...

微服务理解篇

一 :架构演变 1 单体架构: 简单理解为一个服务涵盖所有需求功能2 垂直架构: 按照业务功能将单体架构拆分成小模块服务, 如:订单系统,用户系统,商品系统 ##缺点 引入分布式事务,分布式锁等,优点:模块解耦## 垂直拆分:根据业务层级拆分,比如商城的订单系统,用户系统,商品系统…...

项目篇:基于TCP通信模型的外卖软件实现

一、基本成员及功能实现 本项目主要由服务器&#xff0c;消费者&#xff0c;商家&#xff0c;外卖员组成。基本的功能如下。 对所有人&#xff1a; 1、可以注册登录 2、可以修改个人信息 3、可以销户 商家&#xff1a; 1、注册时需要填写售卖商品信息 2、可以修改商品信…...

深入浅出 diffusion(2):pytorch 实现 diffusion 加噪过程

我在上篇博客深入浅出 diffusion&#xff08;1&#xff09;&#xff1a;白话 diffusion 原理&#xff08;无公式&#xff09;中介绍了 diffusion 的一些基本原理&#xff0c;其中谈到了 diffusion 的加噪过程&#xff0c;本文用pytorch 实现下到底是怎么加噪的。 import torch…...

【软件测试】学习笔记-构建并执行 JMeter 脚本的正确姿势

有些团队在组建之初往往并没有配置性能测试人员&#xff0c;后来随着公司业务体量的上升&#xff0c;开始有了性能测试的需求&#xff0c;很多公司为了节约成本会在业务测试团队里选一些技术能力不错的同学进行性能测试&#xff0c;但这些同学也是摸着石头过河。他们会去网上寻…...

iOS 面试 Swift基础题

一、Swift 存储属性和计算属性比较&#xff1a; 存储型属性:用于存储一个常量或者变量 计算型属性: 计算性属性不直接存储值,而是用 get / set 来取值 和 赋值,可以操作其他属性的变化. 计算属性可以用于类、结构体和枚举&#xff0c;存储属性只能用于类和结构体。存储属性可…...

(七)for循环控制

文章目录 用法while的用法for的用法两者之间的联系可以相互等价用for改写while示例for和while的死循环怎么写for循环见怪不怪表达式1省略第一.三个表达式省略&#xff08;for 改 while&#xff09;全省略即死循环&#xff08;上面已介绍&#xff09; 用法 类比学习while语句 …...

ASP .NET Core Api 使用过滤器

过滤器说明 过滤器与中间件很相似&#xff0c;过滤器&#xff08;Filters&#xff09;可在管道&#xff08;pipeline&#xff09;特定阶段&#xff08;particular stage&#xff09;前后执行操作。可以将过滤器视为拦截器&#xff08;interceptors&#xff09;。 过滤器级别范围…...

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服务器&#xff0c;我想用live555封装一个第三方库&#xff0c;接收流数据搭建Rtsp服务器&#xff1b;预想接口如下&#xff1a; class LiveRtspServer { public:/***brief构造一…...

Apache孵化器领路人与导师的职责

对于捐赠到 ASF 孵化器的项目来说&#xff0c; ASF 孵化器项目管理委员会&#xff08;IPMC&#xff09;的成员会扮演两个角色&#xff0c;一个 孵化器领路人&#xff08;Champion&#xff09;&#xff0c;另外一个是孵化器导师&#xff08;Mentor&#xff09;。 本文源自 ALC …...

【C++中STL】set/multiset容器

set/multiset容器 Set基本概念set构造和赋值set的大小和交换set的插入和删除set查找和统计 set和multiset的区别pair对组两种创建方式 set容器排序 Set基本概念 所有元素都会在插入时自动被排序。 set/multist容器属于关联式容器&#xff0c;底层结构属于二叉树。 set不允许容…...

别再只用四线制SPI了!用菊花链连接多个传感器,Arduino引脚不够的救星

菊花链SPI&#xff1a;突破Arduino引脚限制的多传感器连接方案 当你在智能温室项目中需要同时监测温度、湿度和光照强度&#xff0c;却发现Arduino Uno的GPIO引脚已经捉襟见肘时&#xff0c;传统四线制SPI的局限性就暴露无遗。每个新增的传感器都意味着多占用一个宝贵的片选引…...

Android设备性能优化:Universal Android Debloater的技术实现与应用指南

Android设备性能优化&#xff1a;Universal Android Debloater的技术实现与应用指南 【免费下载链接】universal-android-debloater Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery li…...

保姆级教程:用MQTT.fx客户端连接电信AEP物联网平台,实现设备数据上报与远程控制

从零到一&#xff1a;用MQTT.fx玩转电信AEP物联网平台全流程实战 在物联网开发领域&#xff0c;电信AEP平台作为国内主流物联网云服务平台之一&#xff0c;为开发者提供了从设备接入到数据管理的完整解决方案。而MQTT.fx作为轻量级MQTT客户端工具&#xff0c;因其简洁直观的界面…...

Double Q-learning实战:如何用Python解决过估计问题(附代码示例)

Double Q-learning实战&#xff1a;如何用Python解决过估计问题&#xff08;附代码示例&#xff09; 强化学习中的Q-learning算法因其简洁高效而广受欢迎&#xff0c;但在某些场景下会出现严重的过估计问题。本文将深入探讨这一现象的本质&#xff0c;并手把手教你用Python实现…...

OpenClaw学习路径:从Qwen3-32B镜像体验到复杂自动化任务设计

OpenClaw学习路径&#xff1a;从Qwen3-32B镜像体验到复杂自动化任务设计 1. 为什么需要分阶段学习OpenClaw&#xff1f; 第一次接触OpenClaw时&#xff0c;我被它"无所不能"的自动化能力震撼了——这个开源框架能让AI像人类一样操作我的电脑&#xff0c;完成文件整…...

技术小白AI入门避坑指南:避开4大雷区,高效进阶不走弯路

技术小白AI入门避坑指南&#xff1a;避开4大雷区&#xff0c;高效进阶不走弯路 前言&#xff1a;作为技术小白&#xff0c;入门AI的路上&#xff0c;最可怕的不是“基础薄弱”&#xff0c;而是“走偏方向”——明明付出了时间和精力&#xff0c;却因为踩中误区&#xff0c;要么…...

告别重复劳动:OpenClaw+nanobot批量重命名与整理照片实战

告别重复劳动&#xff1a;OpenClawnanobot批量重命名与整理照片实战 1. 为什么需要自动化照片整理 每次旅行回来&#xff0c;面对相机和手机里混杂的几百张照片&#xff0c;整理工作总是让人头疼。手动创建文件夹、按日期地点分类、重命名文件——这些重复劳动不仅耗时&#…...

告别网络烦恼:Stanza 1.5.1英文语言模型离线安装保姆级教程(Anaconda环境专用)

深度解析Stanza 1.5.1英文语言模型离线部署&#xff1a;Anaconda环境全流程实战 在企业内网或学术研究环境中&#xff0c;我们常常面临无法直接访问外部资源的情况。这时&#xff0c;掌握关键工具的离线部署能力就显得尤为重要。今天我们将全面剖析自然语言处理工具Stanza在受限…...

智能客服原型开发:OpenClaw+Qwen3-32B搭建对话系统

智能客服原型开发&#xff1a;OpenClawQwen3-32B搭建对话系统 1. 为什么选择这个技术栈&#xff1f; 去年我接手了一个智能客服系统的预研项目&#xff0c;客户要求两周内交付可演示的原型。传统方案需要前后端开发、对话引擎集成、工单系统对接&#xff0c;时间根本不够。最…...

颠覆性AI语音转换技术深度解析:Retrieval-based-Voice-Conversion-WebUI的5大创新特性揭秘

颠覆性AI语音转换技术深度解析&#xff1a;Retrieval-based-Voice-Conversion-WebUI的5大创新特性揭秘 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI 语音数据小于等于10分钟也可以用来训练一个优秀的变声模型&#xff01; 项目地址: https://gitcode.com/GitHub…...