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

设计模式-行为型模式-访问者模式

        访问者模式难以实现,且应用该模式可能会导致代码可读性变差,可维护性变差,除非必要,不建议使用;

1.访问者模式定义

        允许在运行时将一个或多个操作应用于一组对象,将操作与对象结构分离;

        访问者模式主要解决的是数据与算法的耦合问题,尤其是在数据结构比较稳定,而算法多变的情况下,为了不污染数据本身,访问者会将多种算法独立归档,并在访问数据时根据数据类型自动切换到对应的算法,实现数据的自动响应机制,并确保算法的自由扩展;

1.1 访问者模式优缺点

优点

  • 扩展性好,在不修改对象结构中元素的情况下,为对象结构中的元素添加新的功能;
  • 复用性好,通过访问者来定义整个对象结构通用的功能,从而提高复用程度;
  • 分离无关行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一;

缺点

  • 对象结构变化很困难,在访问者模式中,没增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了开闭原则;
  • 违反了依赖倒置原则,访问者模式依赖了具体类,而没有依赖抽象类;

1.2 访问者模式的使用场景

  • 当对象的数据结构相对稳定,而操作却经常变化的时候。 比如,上面例子中路由器本身的内部构造(也就是数据结构)不会怎么变化,但是在不同操作系统下的操作可能会经常变化,比如,发送数据、接收数据等。
  • 需要将数据结构与不常用的操作进行分离的时候。 比如,扫描文件内容这个动作通常不是文件常用的操作,但是对于文件夹和文件来说,和数据结构本身没有太大关系(树形结构的遍历操作),扫描是一个额外的动作,如果给每个文件都添加一个扫描操作会太过于重复,这时采用访问者模式是非常合适的,能够很好分离文件自身的遍历操作和外部的扫描操作。
  • 需要在运行时动态决定使用哪些对象和方法的时候。 比如,对于监控系统来说,很多时候需要监控运行时的程序状态,但大多数时候又无法预知对象编译时的状态和参数,这时使用访问者模式就可以动态增加监控行为。

2.访问者模式原理

  • 抽象访问者(Visitor):可以是接口或抽象类,定义了一系列操作方法,用来处理所有数据元素,通常为同名的访问方法,并以数据元素作为入参来确定哪个重载方法被调用;
  • 具体访问者(ConcreteVisitor):实现了抽象访问者,可以有多个,每个访问者都需要实现所有数据元素类型的访问重载发方法;
  • 抽象元素类(Element):被访问的数据元素接口,定义了一个接受访问者的方法,每个元素都要可以被访问者访问;
  • 具体元素类(ConcreteElement):具体数据元素实现类,提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法;
  • 对象结构类(ObjectStructure):包含所有可能被访问的数据对象的容器,可以提供数据对象的迭代功能,可以是任意类型的数据结构;
  • 客户端:使用容器并初始化其中各类数据元素,并选择合适的访问者处理容器中的所有数据对象;

3.访问者模式的实现

【实例】

        以超市购物为例,假设超市中的两类商品:糖果、酒水进行售卖。我们可以忽略每种商品的计价方法,因为最终结账时由收银员统一集中处理,在商品类中添加计价方法是不合理的设计;

【代码】

        访问者接口

public interface Visitor {public void visit(Wine wine);  //酒类重载方法public void visit(Candy candy);  //糖果重载方法
}

        接待者接口

public interface Acceptable {//接收所有的Visitor访问者的子类实现类public void accept(Visitor visitor);
}

        糖果类(酒类类似)

public class Candy extends Product implements Acceptable{public Candy(String name, LocalDate producedDate, double price) {super(name, producedDate, price);}@Overridepublic void accept(Visitor visitor) {//accept实现方法中调用访问者并将自己 "this" 传回。this是一个明确的身份,不存在任何泛型visitor.visit(this);}
}

        具体访问者——折扣计价访问者

public class DiscountVisitor implements Visitor {private LocalDate billDate;public DiscountVisitor(LocalDate billDate) {this.billDate = billDate;System.out.println("结算日期: " + billDate);}@Overridepublic void visit(Candy candy) {System.out.println("糖果: " + candy.getName());//获取产品生产天数long days = billDate.toEpochDay() - candy.getProducedDate().toEpochDay();if(days > 180){System.out.println("超过半年的糖果,请勿食用!");}else{double rate = 0.9;double discountPrice = candy.getPrice() * rate;System.out.println("糖果打折后的价格"+NumberFormat.getCurrencyInstance().format(discountPrice));}}@Overridepublic void visit(Wine wine) {System.out.println("酒类: " + wine.getName()+",无折扣价格!");System.out.println("原价: "+NumberFormat.getCurrencyInstance().format(wine.getPrice()));}
}

        客户端

public class Client {public static void main(String[] args) {//模拟添加多个商品的操作List<Acceptable> products = Arrays.asList(new Candy("金丝猴奶糖",LocalDate.of(2022,6,10),10.00),new Wine("衡水老白干",LocalDate.of(2020,6,10),100.00));Visitor visitor = new DiscountVisitor(LocalDate.of(2022,10,17));for (Acceptable product : products) {product.accept(visitor);}}
}

相关文章:

设计模式-行为型模式-访问者模式

访问者模式难以实现&#xff0c;且应用该模式可能会导致代码可读性变差&#xff0c;可维护性变差&#xff0c;除非必要&#xff0c;不建议使用&#xff1b; 1.访问者模式定义 允许在运行时将一个或多个操作应用于一组对象&#xff0c;将操作与对象结构分离&#xff1b; 访问者…...

探索Oracle数据库的多租户特性:架构、优势与实践

在云计算和大数据时代&#xff0c;多租户架构成为数据库设计中的一个重要趋势。Oracle数据库的多租户选项&#xff08;Multitenant&#xff09;允许单个数据库实例支持多个独立数据库&#xff08;称为容器数据库和可插拔数据库&#xff09;&#xff0c;每个数据库都有自己的数据…...

Hack The Box-Sightless

总体思路 CVE-2022-0944->密码破解->chrome调试->PHP-FPM命令执行 信息收集&端口利用 nmap -sSVC sightless.htbStarting Nmap 7.94SVN ( https://nmap.org ) at 2024-09-11 08:40 CST Nmap scan report for sightless.htb Host is up (0.84s latency). Not sh…...

Linux驱动开发-字符设备驱动开发

linux 驱动开发1. 驱动程序的类型2. 驱动开发流程字符设备驱动 1. 基本概念2. 字符设备驱动的基本结构 架构字符设备驱动开发中常用的 API示例以下代码加入了设备类和设备实例的创建 linux 驱动开发 1. 驱动程序的类型 在 Linux 中&#xff0c;驱动程序主要有以下几种类型&am…...

好用的电脑录屏软件有哪些?推荐4款专业工具。

不同系统的电脑上面带有的录屏功能不一样&#xff0c;比如win10上面有Xbox game bar,Mac系统则用的是QuickTime Player&#xff0c;或者是使用快捷键“CommandShift5”。但更方便的&#xff0c;我自己认为是使用一些专业的录屏软件&#xff0c;他门的录制模式多&#xff0c;兼容…...

web基础之XSS

一、搭建XSS平台 安装 1、我这里安装在本地的Phpstudy上&#xff0c;安装过程就是一路下一步&#xff08;可以改安装路径&#xff09;&#xff0c;附上下载链接&#xff1a; # 官网&#xff1a;https://www.xp.cn/download.html# 蓝莲花 - github下载 https://github.com/fi…...

目标检测-小目标检测方法

小目标检测是计算机视觉中的一个挑战性问题&#xff0c;因为小目标往往在图像中占据的像素较少&#xff0c;容易被背景或其他物体干扰。为了有效地进行小目标检测&#xff0c;研究人员和工程师提出了多种方法和算法来提高检测精度。以下是一些针对小目标检测的有效方式和算法&a…...

连接数据库(以MySQL为例)

文章目录 前言一、数据库是什么&#xff1f;二、连接步骤 1.手动导入驱动包2.连接数据库总结 前言 面对应用程序的开发&#xff0c;普遍需要保存用户的海量数据。保存粮的库叫粮库&#xff0c;保存水的库叫水库&#xff0c;那么保存数据的库自然叫数据库。有了数据库&#xff0…...

Mysql高级教程

1.安装部署 安装依赖性&#xff1a; [rootmysql-node10 ~]# dnf install cmake gcc-c openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el7_4.x86_64.rpm rpcgen.x86_64 下载并解压源码包 [rootmysql-node10 ~]# tar zxf mysql-boost-5.7.44.tar.gz [rootmysql-no…...

基于Ubuntu2404搭建mysql8配置远程访问

使用系统为Ubuntu2404&#xff0c;mysql8版本为8.0.36 安装mysql apt install -y mysql-server设置开机自启动 systemctl enable --now mysql修改密码&#xff0c;似乎是bug&#xff0c;修改密码第一次不成功&#xff0c;第二次可以 mysql use mysql; update user set Host…...

前端工程师职业发展路线图

在前端开发领域&#xff0c;从一个新手成长为一名资深工程师需要经过一系列的学习和实践。以下是一份详细的前端工程师职业发展路线图&#xff0c;包括了从基础到高级的各个阶段。 入门阶段 1. 学习基础技术 HTML/HTML5&#xff1a;掌握网页结构和语义化标签的使用。CSS/CSS…...

人工智能(AI)正在以前所未有的速度融入我们生活的方方面面

人工智能将融入我们生活的方方面面 人工智能&#xff08;AI&#xff09;正在以前所未有的速度融入我们生活的方方面面&#xff0c;这种趋势在未来几年乃至几十年内将会持续加速。以下是一些人工智能已经或即将在各个领域产生深远影响的例子&#xff1a; 智能家居&#xff1a;…...

OpenCV-模板匹配多个目标

文章目录 一、基本概念二、基本步骤1.图像准备2.图像预处理3.执行模板匹配4.定位匹配区域5.处理多个匹配6.优化和验证 三、代码实现1.图片读取2.图像预处理3.模板匹配4.绘制矩形框 三、总结 模型匹配&#xff08;Model Matching&#xff09;是一个广泛应用的概念&#xff0c;其…...

uniapp 原生插件开发 UI

前言&#xff1a; 在集成某些特定 原生SDK的时候&#xff0c;它本身是带UI控件的。当我们使用 uniapp 开发app的时候实是 可以使使用 nvue 页面&#xff0c;以 weex 的方式嵌入原生的UI控件。 我这边的场景是 接入连连app的支付&#xff0c;它有个自己的密码键盘 控件是原生的页…...

性能测试-性能分析与调优原理总结

性能分析与调优如何下手&#xff0c;先从硬件开始&#xff0c;还是先从代码或数据库。 从操作系统&#xff08;CPU调度&#xff0c;内存管理&#xff0c;进程调度&#xff0c;磁盘I/O&#xff09;、网络、协议&#xff08;HTTP&#xff0c; TCP/IP &#xff09;&#xff0c;还是…...

【机器学习】4 ——熵

机器学习4 ——熵 文章目录 机器学习4 ——熵前言 前言 熵衡量随机变量不确定性&#xff0c;由克劳德香农&#xff08;Claude Shannon&#xff09;在1948年提出&#xff0c;称为香农熵。反映了一个系统中信息的混乱程度或信息量。 其定义为&#xff1a; H ( P ) − ∑ x P …...

linux命令用于删除文本文件中的重复行的命令uniq详解

目录 一、概述 二、基本用法 1、uniq 命令的基本语法 2、常用选项 3、获取帮助 三、主要功能 1. 识别并删除相邻重复行 2. 保留重复行的第一个实例 3. 统计重复次数 4. 忽略指定列的比较 四、示例 1. 删除相邻重复行 2. 显示每一行及其重复次数 3. 只显示重复行 4. …...

PHP智驭未来悦享生活智慧小区物业管理小程序系统源码

智驭未来&#xff0c;悦享生活 —— 探索智慧小区物业管理小程序 一、引言&#xff1a;智慧生活的新篇章 在这个日新月异的时代&#xff0c;科技正以前所未有的速度改变着我们的生活。从智能家居到智慧城市&#xff0c;每一处都闪耀着智慧的光芒。而今天&#xff0c;我要带大家…...

深度学习:怎么看pth文件的参数

.pth 文件是 PyTorch 模型的权重文件&#xff0c;它通常包含了训练好的模型的参数。要查看或使用这个文件&#xff0c;你可以按照以下步骤操作&#xff1a; 1. 确保你有模型的定义 你需要有创建这个 .pth 文件时所用的模型的代码。这意味着你需要有模型的类定义和架构。 2. …...

MMLU-Pro 基准测试数据集上线,含 12k 个跨学科复杂问题,难度提升,更具挑战性!DeepSeek 数学模型一键部署

在大语言模型 (LLM) 蓬勃发展的时代&#xff0c;诸如大规模多任务语言理解 (MMLU) 之类的基准测试&#xff0c;在推动 AI 于不同领域的语言理解与推理能力迈向极限方面&#xff0c;发挥着至关重要的关键作用。 然而&#xff0c;伴随模型的持续改进与优化&#xff0c;LLM 在这些…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

git: early EOF

macOS报错&#xff1a; Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

C# WPF 左右布局实现学习笔记(1)

开发流程视频&#xff1a; https://www.youtube.com/watch?vCkHyDYeImjY&ab_channelC%23DesignPro Git源码&#xff1a; GitHub - CSharpDesignPro/Page-Navigation-using-MVVM: WPF - Page Navigation using MVVM 1. 新建工程 新建WPF应用&#xff08;.NET Framework) 2.…...

ABAP设计模式之---“Tell, Don’t Ask原则”

“Tell, Don’t Ask”是一种重要的面向对象编程设计原则&#xff0c;它强调的是对象之间如何有效地交流和协作。 1. 什么是 Tell, Don’t Ask 原则&#xff1f; 这个原则的核心思想是&#xff1a; “告诉一个对象该做什么&#xff0c;而不是询问一个对象的状态再对它作出决策。…...

Centos 7 服务器部署多网站

一、准备工作 安装 Apache bash sudo yum install httpd -y sudo systemctl start httpd sudo systemctl enable httpd创建网站目录 假设部署 2 个网站&#xff0c;目录结构如下&#xff1a; bash sudo mkdir -p /var/www/site1/html sudo mkdir -p /var/www/site2/html添加测试…...