访问者模式 行为型设计模式之九

1.定义

        在不改变数据结构的前提下,增加作用于一组对象元素的新功能。

2.动机

  1. 访问者模式适用于数据结构相对稳定的系统
  2. 它把数据结构和作用于数据结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。
  3. 访问者模式的目的是要把处理从数据结构分离出来。如果这样的系统有比较稳定的数据结构,又有已与变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得更容易。反之亦然。

        一句话总结就是,访问者不会改变原有系统的数据结构,而只是使用原有系统的数据去实现自己的功能。这个实现的功能可以自己定制,但是原有系统需要留出这样的访问者应用接口。

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.组成结构

  1. Visitor 是抽象访问者,为该对象结构中的 ConcreteElement 的每一个类声明一个 visit 操作
  2. ConcreteVisitor :是一个具体的访问值 实现每个有 Visitor 声明的操作,是每个操作实现的部分.
  3. ObjectStructure :能枚举它的元素, 可以提供一个高层的接口,用来允许访问者访问元素
  4. Element: 定义一个 accept  方法,接收一个访问者对象
  5. ConcreteElement: 为具体元素,实现了 accept  方法

5.引用

C++设计模式——访问者模式 - 冰糖葫芦很乖 - 博客园 (cnblogs.com)

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

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

相关文章

消息驱动 —— SpringCloud Stream

Stream 简介 Spring Cloud Stream 是用于构建消息驱动的微服务应用程序的框架&#xff0c;提供了多种中间件的合理配置 Spring Cloud Stream 包含以下核心概念&#xff1a; Destination Binders&#xff1a;目标绑定器&#xff0c;目标指的是 Kafka 或者 RabbitMQ&#xff0…

信息增益,经验熵和经验条件熵——决策树

目录 1.经验熵 2.经验条件熵 3.信息增益 4.增益比率 5.例子1 6.例子2 在决策树模型中&#xff0c;我们会考虑应该选择哪一个特征作为根节点最好&#xff0c;这里就用到了信息增益 通俗上讲&#xff0c;信息增益就是在做出判断时&#xff0c;该信息对你影响程度的大小。比…

抖音seo源代码开源部署----基于开放平台SaaS服务

抖音SEO搜索是什么&#xff1f; 抖音SEO搜索是指在抖音平台上进行搜索引擎优化&#xff08;Search Engine Optimization&#xff09;的一种技术手段。 通过优化抖音账号、发布内容和关键词等&#xff0c;提高抖音视频在搜索结果中的排名&#xff0c;从而增加视频曝光量和用户点…

ValueError: high is out of bounds for int32 报错

问题描述&#xff1a; 笔者在Windows 64位平台跑一个在Ubuntu上运行正常的程序时&#xff0c;出现了以下报错&#xff1a; 具体为&#xff1a; seed np.random.randint(0, 2 ** 32) # make a seed with numpy generatorFile "mtrand.pyx", line 763, in numpy.ra…

紫光展锐完成Android 14同步升级

近日&#xff0c;紫光展锐宣布&#xff0c;展锐5G移动平台T820、T770、T760、T750以及4G平台T619、T616、T612、T606和SC9863A&#xff0c;完成Android 14的同步升级。同时&#xff0c;紫光展锐简化了OEM和ODM厂商向最新版Android操作系统升级的步骤&#xff0c;大幅降低整体工…

Moonbeam Ignite强势回归

参与Moonbeam上最新的流动性计划 还记得新一轮的流动性激励计划吗&#xff1f;Moonbeam Ignite社区活动带着超过300万枚GLMR奖励来啦&#xff01;体验新项目&#xff0c;顺便薅一把GLMR羊毛。 本次Moonbeam Ignite活动的参与项目均为第二批Moonbeam生态系统Grant资助提案中获…

BaseQuickAdapter触底刷新实现

触底刷新实现 使用BaseQuickAdapter&#xff0c;在适配器中实现 LoadMoreModule即可&#xff0c;如下加上即可&#xff0c;无需多写代码 以下为分页实现&#xff1a; 视图中 // 获取加载更多模块loadMoreModule blogAdapter.getLoadMoreModule();loadMoreModule.setOnLoadMo…

无线振弦采集仪在岩土工程中如何远程监测和远程维护

无线振弦采集仪在岩土工程中如何远程监测和远程维护 随着岩土工程施工的不断发展和科技水平的不断提高&#xff0c;远程监测和远程维护设备也得到了广泛关注和应用。无线振弦采集仪是一种广泛应用于岩土工程中的测量仪器&#xff0c;在现代化施工中扮演着重要的角色。本文将就…

2023学生近视了用什么台灯好呢?好用预防近视的护眼台灯推荐

自从护眼台灯能够帮助孩子在写作业时能够缓解视觉疲劳以来&#xff0c;许多家长已经给孩子安排上来护眼台灯&#xff0c;护眼台灯能够提供良好的照明环境&#xff0c;并且能够让我们专心学习提高工作效率。但由于护眼台灯含有独家的黑科技技术&#xff0c;价格始终居高不下&…

【微信小程序开发】一文学会使用CSS样式布局与美化

引言 在微信小程序开发中&#xff0c;CSS样式布局和美化是非常重要的一部分&#xff0c;它能够为小程序增添美感&#xff0c;提升用户体验。本文将介绍如何学习使用CSS进行样式布局和美化&#xff0c;同时给出代码示例&#xff0c;帮助开发者更好地掌握这一技巧。 一、CSS样式布…

ssm+vue的公司人力资源管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的公司人力资源管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

【Overload游戏引擎分析】画场景栅格的Shader分析

Overload引擎地址&#xff1a; GitHub - adriengivry/Overload: 3D Game engine with editor 一、栅格绘制基本原理 Overload Editor启动之后&#xff0c;场景视图中有栅格线&#xff0c;这个在很多软件中都有。刚开始我猜测它应该是通过绘制线实现的。阅读代码发现&#xff0…

漏刻有时物联网环境态势感知大数据(设备列表、动态折线图)

物联网环境下的态势感知是指对物联网环境中的各种要素进行全面、实时、准确的监测、分析和预测,以实现网络态势的全面掌握和安全威胁的及时响应和处理。具体而言,态势感知以物联网环境为基础,利用各类传感器、数据采集设备和其他相关工具,对物联网设备、资产、数据流等进行…

使用VHDL语言实现简单的卷积神经网络

下面使用VHDL编写一个完整的卷积神经网络(CNN)是一项非常复杂且耗时的任务,需要详细的设计和实现过程。在这里,我将提供一个简化版本的示例,展示如何使用VHDL实现一个基本的卷积层。 首先,我们需要定义一些参数来描述卷积层的结构和操作。在这个示例中,我们假设输入图像…

【Python】语言学习

之前总觉得python简单&#xff0c;不当回事&#xff0c;直到自己动手连输出都写不出来。。于是开一篇专门练python的博客。 输出 Python初相识 (educoder.net) 常规输出 print("向上&#xff1a;%.2f,向下&#xff1a;%.2f" %(pow(1.001, 365),pow(0.999, 365))) …

论文笔记 A theory of learning from different domains

domain adaptation 领域理论方向的重要论文. 这篇笔记主要是推导文章中的定理, 还有分析定理的直观解释. 笔记中的章节号与论文中的保持一致. 1. Introduction domain adaptation 的设定介绍: 有两个域, source domain 与 target domain. source domain: 一组从 source dist.…

【剑指Offer】12.矩阵中的路径

题目 请设计一个函数&#xff0c;用来判断在一个n乘m的矩阵中是否存在一条包含某长度为len的字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向下移动一个格子。如果一条路径经过了…

Java 面向对象的三大特性

面向对象编程有三大特征: 封装、继承和多态。 1.封装 1&#xff09;封装介绍 封装(encapsulation)就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起数据被保护在内部.程序的其它部分只有通过被授权的操作[方法],才能对数据进行操作。 2&#xff09;封装的理解和好处 隐…

Springboot使用ProcessBuilder创建系统进程执行shell命令备份数据库

文章目录 概要1、查看mysql版本2、相关依赖3、具体代码技术细节 概要 Springboot执行shell命令备份数据库。 1、查看mysql版本 mysql --version2、相关依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

【力扣-每日一题】901. 股票价格跨度

暴力解法&#xff1a; class StockSpanner { private:vector<int> pri; public:StockSpanner() {}int next(int price) {pri.emplace_back(price);int count0;for(int ipri.size()-1;i>0;i--){if(pri[i]<price)count;else break;}return count;} };/*** Your Stoc…