访问者模式 行为型设计模式之九
1.定义
在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
2.动机
- 访问者模式适用于数据结构相对稳定的系统
- 它把数据结构和作用于数据结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。
- 访问者模式的目的是要把处理从数据结构分离出来。如果这样的系统有比较稳定的数据结构,又有已与变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得更容易。反之亦然。
一句话总结就是,访问者不会改变原有系统的数据结构,而只是使用原有系统的数据去实现自己的功能。这个实现的功能可以自己定制,但是原有系统需要留出这样的访问者应用接口。
3.示例代码
一台电脑中有很多组件,CPU、GPU、硬盘。维修人员对电脑进行整体维修时,需要对各部件依次进行维修,而且每部件具体的维修方式不同。不同的维修人员对相同的部件维修方式可能也不同。维修人员就是访问者。访问者类中实现了针对不同部件的维修方式。电脑就是被访问者。被访问者提供访问接口,使用访问者类中实现的不同部件维修方式,对内部部件进行访问。
#include <iostream>
#include <list>
using namespace std;class Visitor;//组成Computer的各组件基类
class Element
{
public:Element(string strName) :m_strName(strName) {}string GetName(){return m_strName;}//组件接受访问者访问的接口virtual void AcceptVisitor(Visitor* pVisitor) = 0;private://组件的标识名称string m_strName;
};//访问者基类,针对不同组件,提供不同的访问接口
class Visitor
{
public:virtual void VisitCPU(Element* pEle) = 0;virtual void VisitGPU(Element* pEle) = 0;virtual void VisitDISK(Element* pEle) = 0;
};//Computer类,由各组件组成,访问者访问Computer时将依次访问各组件
class Computer
{
public:~Computer(){for (Element* pElement : m_listEle){delete pElement;}}void AddElement(Element* pEle){m_listEle.push_back(pEle);}void DelElement(Element* pEle){m_listEle.remove(pEle);}//访问者访问Computer时将依次访问各组件void AcceptVisitor(Visitor* pVisitor){for (Element* pElement : m_listEle){pElement->AcceptVisitor(pVisitor);}}private:list<Element*> m_listEle;
};//访问者实现类,实现各自的访问方法
class VisitorA : public Visitor
{
public:void VisitCPU(Element* pEle){printf("Visitor A record CPU's name:%s\n", pEle->GetName().c_str());}void VisitGPU(Element* pEle){printf("Visitor A do nothing to GPU:%s\n", pEle->GetName().c_str());}void VisitDISK(Element* pEle){printf("Visitor A change DISK:%s\n", pEle->GetName().c_str());}
};class VisitorB : public Visitor
{
public:void VisitCPU(Element* pEle){printf("Visitor B do nothing to CPU:%s\n", pEle->GetName().c_str());}void VisitGPU(Element* pEle){printf("Visitor B record GPU's name:%s\n", pEle->GetName().c_str());}void VisitDISK(Element* pEle){printf("Visitor B do nothing to DISK:%s\n", pEle->GetName().c_str());}
};//组件的实现类,调用访问者相应的访问方法
class CPU :public Element
{
public:CPU(string strName) :Element(strName) {}void AcceptVisitor(Visitor* pVisitor){pVisitor->VisitCPU(this);}
};class GPU :public Element
{
public:GPU(string strName) :Element(strName) {}void AcceptVisitor(Visitor* pVisitor){pVisitor->VisitGPU(this);}
};class Disk :public Element
{
public:Disk(string strName) :Element(strName) {}void AcceptVisitor(Visitor* pVisitor){pVisitor->VisitDISK(this);}
};int main()
{Computer oComputer;oComputer.AddElement(new CPU("i9-10980XE"));oComputer.AddElement(new GPU("Titan RTX"));oComputer.AddElement(new Disk("HOF PRO M.2"));VisitorA oVisitorA;VisitorB oVisitorB;oComputer.AcceptVisitor(&oVisitorA);oComputer.AcceptVisitor(&oVisitorB);return 0;
}
4.组成结构
- Visitor 是抽象访问者,为该对象结构中的 ConcreteElement 的每一个类声明一个 visit 操作
- ConcreteVisitor :是一个具体的访问值 实现每个有 Visitor 声明的操作,是每个操作实现的部分.
- ObjectStructure :能枚举它的元素, 可以提供一个高层的接口,用来允许访问者访问元素
- Element: 定义一个 accept 方法,接收一个访问者对象
- ConcreteElement: 为具体元素,实现了 accept 方法
5.引用
C++设计模式——访问者模式 - 冰糖葫芦很乖 - 博客园 (cnblogs.com)
相关文章:
访问者模式 行为型设计模式之九
1.定义 在不改变数据结构的前提下,增加作用于一组对象元素的新功能。 2.动机 访问者模式适用于数据结构相对稳定的系统它把数据结构和作用于数据结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式的目的是要把处理从数据结构…...
JVM垃圾回收之JVM GC算法探究
JVM垃圾回收之JVM GC算法探究 在Java虚拟机(JVM)中,垃圾回收(Garbage Collection,GC)是自动管理内存的重要机制,它负责回收程序中不再使用的对象所占用的内存。GC算法是垃圾回收的核心…...
Django 前端模板显示换行符、日期格式
linebreaksbr 显示换行符 <td>{{ data.sku_list|default:"无"|linebreaksbr }}</td> date:"Y年m月d日 H:i" 设置日期格式 <td>{{ data.submit_time|date:"Y年m月d日 H:i" }}</td> 其他语法 forloop 获取循环的索引 …...
Aurora中的策略模式和模板模式
Aurora中的策略模式和模板模式 在aurora中为了方便以后的扩展使用了策略模式和模板模式实现图片上传和搜索功能,能够在配置类中设置使用Oss或者minio上传图片,es或者mysql文章搜索。后续有新的上传方式或者搜索方式只需要编写对应的实现类即可ÿ…...
Ubuntu 22.04 安装系统 手动分区 针对只有一块硬盘 lvm 单独分出/home
自动安装的信息 参考自动安装时产生的分区信息 rootyeqiang-MS-7B23:~# fdisk /dev/sdb -l Disk /dev/sdb:894.25 GiB,960197124096 字节,1875385008 个扇区 Disk model: INTEL SSDSC2KB96 单元:扇区 / 1 * 512 512 字节 扇区大…...
Android系统定制之监听USB键盘来判断是否弹出软键盘
一.项目背景 在设备上弹出软键盘,会将一大部分UI遮挡起来,造成很多图标无法看到和点击,使用起来不方便,因此通过插入usb键盘输入代替软键盘,但是点击输入框默认会弹出软键盘,因此想要插入USB键盘时,默认关闭软键盘,拔出键盘时再弹出,方便用户使用 二.设计思路 2.1…...
LeakyReLU激活函数
nn.LeakyReLU 是PyTorch中的Leaky Rectified Linear Unit(ReLU)激活函数的实现。Leaky ReLU是一种修正线性单元,它在非负数部分保持线性,而在负数部分引入一个小的斜率(通常是一个小的正数),以防…...
Qt单一应用实例判断
原本项目中使用QSharedMemory的方法来判断当前是否已存在运行的实例,但在MacOS上,当程序异常崩溃后,QSharedMemory没有被正常销毁,导致应用程序无法再次被打开。 对此,Qt assistant中有相关说明: 摘抄 qt-s…...
企业AI工程化之路:如何实现高效、低成本、高质量的落地?
MLOps工程实践 概述面临挑战目的内容简介读者对象专家推荐目录 写在末尾: 主页传送门:📀 传送 概述 作为计算机科学的一个重要领域,机器学习也是目前人工智能领域非常活跃的分支之一。机器学习通过分析海量数据、总结规律&#x…...
最短路径专题8 交通枢纽 (Floyd求最短路 )
题目: 样例: 输入 4 5 2 0 1 1 0 2 5 0 3 3 1 2 2 2 3 4 0 2 输出 0 7 思路: 由题意,绘制了该城市的地图之后,由给出的 k 个编号作为起点,求该点到各个点之间的最短距离之和最小的点是哪个,并…...
文件扫描模块
文章目录 前言文件扫描模块设计初级扫描方案一实现单线程扫描整合扫描步骤 设计初级扫描方案二周期性扫描 总结 前言 我们这个模块考虑的是数据库里面的内容从哪里获取。 获取完成后,这时候,我们就需要把目录里面文件/子文件都获取出来,并存入数据库。 文件扫描模…...
MySQL之主从复制
概述: 将主库的数据 变更同步到从库,从而保证主库和从库数据一致。 它的作用是 数据备份,失败迁移,读写分离,降低单库读写压力 原理: 主服务器上面的任何修改都会保存在二进制日志( Bin-log日志…...
[leetcode 单调栈] 901. 股票价格跨度 M
设计一个算法收集某些股票的每日报价,并返回该股票当日价格的 跨度 。 当日股票价格的 跨度 被定义为股票价格小于或等于今天价格的最大连续日数(从今天开始往回数,包括今天)。 例如,如果未来 7 天股票的价格是 [100…...
Java线程池:并发编程的利器
Java线程池:并发编程的利器 在多任务、高并发的时代,Java并发编程显得尤为重要。其中,Java线程池是一种高效的管理线程的工具,能够提高应用程序的性能和响应速度。本文将深入探讨Java线程池的工作原理、应用场景以及简单示例&…...
ARM硬件断点
hw_breakpoint 是由处理器提供专门断点寄存器来保存一个地址,是需要处理器支持的。处理器在执行过程中会不断去匹配,当匹配上后则会产生中断。 内核自带了硬件断点的样例linux-3.16\samples\hw_breakpoint\data_breakpoint.c static void sample_hbp_h…...
Java使用WebSocket(基础)
准备一个html页面 <!DOCTYPE HTML> <html> <head><meta charset"UTF-8"><title>WebSocket Demo</title> </head> <body><input id"text" type"text" /><button onclick"send()&…...
图像处理与计算机视觉--第五章-图像分割-自适应阈值分割
文章目录 1.自适应阈值分割介绍2.自适应阈值函数参数解析3.高斯概率函数介绍4.自适应阈值分割核心代码5.自适应阈值分割效果展示6.参考文章及致谢 1.自适应阈值分割介绍 在图片处理过程中,针对铺前进行二值化等操作的时候,我们希望能够将图片相应区域内所…...
记一次问题排查
1785年,卡文迪许在实验中发现,把不含水蒸气、二氧化碳的空气除去氧气和氮气后,仍有很少量的残余气体存在。这种现象在当时并没有引起化学家的重视。 一百多年后,英国物理学家瑞利测定氮气的密度时,发现从空气里分离出来…...
【Spring Boot】创建一个 Spring Boot 项目
创建一个 Spring Boot 项目 1. 安装插件2. 创建 Spring Boot 项目3. 项目目录介绍和运行注意事项 1. 安装插件 IDEA 中安装 Spring Boot Helper / Spring Assistant / Spring Initializr and Assistant插件才能创建 Spring Boot 项⽬ (有时候不用安装,直…...
flutter中使用缓存
前言 在flutter项目中使用ListView或者PageView等有滚动条组件的时候,切换页面的时候,再切换回来会丢失之前的滑动状态,这个时候就需要需要使用缓存功能 缓存类 import package:flutter/material.dart;class KeepAliveWrapper extends Sta…...
告别样本不平衡噩梦:Focal Loss 让你的模型学会“划重点”
我说的不是 Python 那个 HTTPX 客户端,而是 ProjectDiscovery 出的 httpx。官方对它的定义很直接: 一个高性能、面向多探针的 HTTP 工具包支持高并发下对 URL、主机、CIDR 等 目标做 HTTP 层探测,并尽量保证结果稳定性。 它本质上不是漏洞扫描…...
零基础也能挖洞赚钱?SRC漏洞挖掘从入门到精通,附全套工具包+学习路线!
开篇:为什么说SRC挖洞是安全新手的最佳起点? 凌晨两点,大学生张三盯着电脑屏幕突然跳出的「高危漏洞奖励到账」提示,手抖得差点打翻泡面——这是他挖到人生第一个SRC漏洞(某电商平台的越权访问漏洞)后收到…...
手机号查询QQ技术解析与实战指南
手机号查询QQ技术解析与实战指南 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 问题:数字化时代的身份关联困境 在现代社会,手机号与QQ号作为重要的数字身份标识,其关联查询需求日益凸显。当用户…...
AIVideo一键部署指南:开箱即用的AI视频创作平台
AIVideo一键部署指南:开箱即用的AI视频创作平台 1. 平台概览:从主题到视频的全流程自动化 AIVideo是一款革命性的AI视频创作工具,它能将您的文字主题自动转化为专业级视频作品。想象一下,您只需输入一个简单的想法,比…...
BilibiliDown:专业B站Hi-Res音频下载工具全攻略
BilibiliDown:专业B站Hi-Res音频下载工具全攻略 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bili…...
Vivado综合策略的‘隐藏菜单’:手把手教你用TCL定制专属策略,榨干UltraScale+性能
Vivado综合策略的‘隐藏菜单’:手把手教你用TCL定制专属策略,榨干UltraScale性能 当你在Vivado中点击"Run Synthesis"时,是否曾好奇那些预设策略背后究竟发生了什么?对于大多数FPGA设计,Vivado提供的预设策略…...
openclaw喂饭教程!在 Linux 环境下快速完成安装、初始化与 Web UI 配置
基础示例:单工作表 Excel 转 TXT 以下是将一个 Excel 文件中的第一个工作表转换为 TXT 的完整步骤: 1. 加载并读取Excel文件 from spire.xls import * from spire.xls.common import * workbook Workbook() workbook.LoadFromFile("示例.xlsx"…...
深入浅出:从地平线J5的“安全岛”设计,聊聊车规级SoC的功能安全到底在保什么?
地平线J5的"安全岛"设计:车规芯片如何守护生命线? 清晨7点30分,北京五环路上的一辆新能源车正以60公里时速自动跟车行驶。突然,前车急刹,车载摄像头捕捉到这一信号后,视觉处理芯片必须在0.1秒内完…...
4个Dify工作流配置策略:从基础请求到复杂数据处理的高效实践
4个Dify工作流配置策略:从基础请求到复杂数据处理的高效实践 【免费下载链接】Awesome-Dify-Workflow 分享一些好用的 Dify DSL 工作流程,自用、学习两相宜。 Sharing some Dify workflows. 项目地址: https://gitcode.com/GitHub_Trending/aw/Awesome…...
Fire Dynamics Simulator:火灾动力学模拟的核心引擎与实战应用
Fire Dynamics Simulator:火灾动力学模拟的核心引擎与实战应用 【免费下载链接】fds Fire Dynamics Simulator 项目地址: https://gitcode.com/gh_mirrors/fd/fds 揭示核心价值:为何FDS成为火灾模拟领域的标准工具? 在建筑安全设计、…...
