C++ 大话设计之《访问者模式》(优缺点,设计原理,常用场景)

2023-10-27

访问者模式是一种行为型模式


优点:

能够在不改变对象结构的情况下增加新的操作,使得操作集合可以相对独立地演化。

缺点:

  • 增加新的元素类变得困难,因为每个新元素都必须被访问者类所接受。
  • 此外,如果对象结构中的元素类经常发生变化,那么使用访问者模式可能不是最佳选择。

满足的设计原则:

访问者模式满足了开放封闭原则(Open-Closed Principle,OCP)。这个原则指出软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。访问者模式允许你在不改变对象结构中元素类的情况下定义一个新的操作,这样就可以在不修改现有代码的情况下增加新的功能。
 

常用实例:

访问者模式在开发中的一个常见应用是编译器。编译器通常需要对抽象语法树(AST)进行遍历,以执行诸如类型检查、代码生成等操作。使用访问者模式,可以将这些操作定义为访问者类,然后在遍历AST时调用相应的访问者方法。这样,当需要增加新的操作时,只需定义一个新的访问者类即可,而无需修改AST的结构。

类图:

 代码:

#include "iostream"
#include "vector"

using namespace std;

class ConcreteElementA;
class ConcreteElementB;

class Visitor
{
public:
	virtual void visitConcreteElementA(ConcreteElementA*elementA)=0;
	virtual void visitConcreteElementB(ConcreteElementB*elementB)=0;
};

class Element
{
public:
	virtual void accept(Visitor*visitor)=0;

};

class ConcreteElementA :public Element
{
public:
	void accept(Visitor* visitor)
	{
		visitor->visitConcreteElementA(this);
	}
	void operationA()
	{
		cout<<"ConcreteElementA operation"<<endl;
	}
};

class ConcreteElementB :public Element
{
public:
	void accept(Visitor* visitor)
	{
		visitor->visitConcreteElementB(this);
	}
	
	void operationB()
	{
		cout<<"ConcreteElementB operation"<<endl;
	}


};

class ConcreteVisitor1 :public Visitor
{
public:
	void visitConcreteElementA(ConcreteElementA* elementA)
	{
		elementA->operationA();
	}

	void visitConcreteElementB(ConcreteElementB* elementB)
	{
		elementB->operationB();
	}
};

class ConcreteVisitor2 :public Visitor
{
public:
	void visitConcreteElementA(ConcreteElementA* elementA)
	{
		elementA->operationA();
	}

	void visitConcreteElementB(ConcreteElementB* elementB)
	{
		elementB->operationB();
	}
};



class ConcreteVisitor3 :public Visitor
{
public:
	void visitConcreteElementA(ConcreteElementA* elementA)
	{
		elementA->operationA();
		//可在此处扩展
		cout<<"sss"<<endl;
	}

	void visitConcreteElementB(ConcreteElementB* elementB)
	{
		elementB->operationB();
		//可在此处扩展
		cout << "sss" << endl;
	}
};

class ObjectStructure
{
public:
	void attach(Element* element)
	{
		elements.push_back(element);
	}
	void detach(Element* element)
	{
		for (vector<Element*>::iterator it=elements.begin();it!=elements.end();++it)
		{
			if (*it == element)
			{
				elements.erase(it);
				break;
			}
		}
	}

	void accept(Visitor* visitor)
	{
		for (auto elment : elements)
		{
			elment->accept(visitor);
		}
	}




private:
	vector<Element*>elements;
};

int main()
{
	
	ObjectStructure objectStructure;

	ConcreteElementA elementA;
	ConcreteElementB elementB;

	objectStructure.attach(&elementA);
	objectStructure.attach(&elementB);

	ConcreteVisitor1 visitor1;
	ConcreteVisitor2 visitor2;

	objectStructure.accept(&visitor1);

	objectStructure.accept(&visitor2);




	return 0;

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 大话设计之《访问者模式》(优缺点,设计原理,常用场景) 的相关文章

  • 使用 OpenXML 打开受保护的 Word 文档

    我到处寻找 但找不到任何答案 所有帖子和讨论都是关于创建受保护的帖子和讨论 但没有任何内容可以打开它 我在我的 c 程序中保护了 DOCX 和 DOC 文档 并希望使用 OpenXML 2 5 以编程方式打开它们 我已经使用 Office
  • 寻求有关 cs50“现金”问题集的 C 贪婪算法的帮助[已关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 目标是创建一种算法 该算法接受输入并给出从输入中减去值 25 10 5 1 的次数的输出 代码需要以尽可能贪婪的方式执行此操作 尽可能获取最
  • 在 ASP.NET Core 中全局重用变量

    我必须强制这些变量在我想使用的每个变量上重用 这让我很困难 我需要创建一个类来定义这些变量并在整个程序中使用它们 我怎样才能做到这一点 string RootFolderName Uplaod string ProductPictureFo
  • 资源文件中的控制字符 C#

    我想添加Left To Right控制字符在resource resx文件输入Visual Studio 我在互联网上搜索并找到了一个名为在 NET 资源文件中转义序列的另一种方法 http www devx com tips Tip 34
  • Linq Any 始终返回 true

    我已经使用 Linq to Entities 多年 但这是我第一次遇到这个问题 我有Tips and Items表 每个提示可以有很多项目 我的数据库中只有 3 个项目 编辑项目时 我想确保GivenId对于具有相同提示的项目 字段是唯一的
  • 委托 System.Action 不接受 1 个参数

    那个行动 readonly Action execute public RelayCommand Action execute this execute null public RelayCommand Action execute Fun
  • 带有成员 (operator[]) 函数的 invoke_result

    如何为成员函数正确调用invoke result 或者专门用于运算符成员函数 我试过std invoke result
  • 预期在模拟中调用一次,但使用 Moq 时调用次数为 0 次

    我收到错误 在mock上调用一次 但是0次 下面是我的代码结构 public class GenerateAddress IGenerateAddress public GenerateAddress IAddress createAdd
  • 如何使用 CMake 链接多个库

    我有一些与 DCMTK 相关的代码 如果我从命令行使用 g 我可以成功构建并运行它 这是代码 include dcmtk config osconfig h include dcmtk dcmdata dctk h int main Dcm
  • gcc 的错误?模板类中友元函数的访问控制问题

    我有一个模板类 并在类中定义了一个友元函数 include
  • 清除指针向量[重复]

    这个问题在这里已经有答案了 假设我定义了一个这样的类 class foo private std vector lt int gt v public void bar1 for int i 0 i lt 10 i int a new int
  • 对指针列表进行排序

    我再次发现自己在 C 中的一些非常简单的任务上失败了 有时我希望我能从 Java 中的 OO 中学到所有知识 因为我的问题通常是从像 Java 一样思考开始的 无论如何 我有一个std list
  • ofstream::operator<<(streambuf) 是一种复制文件的缓慢方法

    我需要一种跨平台 无需外部库的复制文件的方式 在我的第一遍中 我想出了 省略错误处理 char buffer LEN ifstream src srcFile ios in ios binary ofstream dest destFile
  • 以 asp-for 作为参数的自定义 ViewComponent

    我想把这个包装起来
  • “未定义对 clrscr() 的引用;” [复制]

    这个问题在这里已经有答案了 include
  • 从 Windows 选择声音并播放它们

    我有一个 WinForms 应用程序 该应用程序有一个 首选项 部分 用户可以在其中选择显示警报时播放哪些声音 是否可以有一个组合框 用户可以从 Windows 存储的声音中进行选择 例如 紧急停止 紧急蜂鸣 等 这些可以在 控制面板 gt
  • boost::bind 会导致开销吗?

    我目前正在从事网络软件方面的工作 它有一个主要类 server这显然代表一个服务器实例 A server实例可以发送请求 并通过回调通知用户响应 代码如下 class server public typedef boost function
  • 作为服务运行时,URLDownloadToFile() 将对象写入缓存中

    我有一个软件 可以将图像下载到工作目录中 然后对其进行处理以创建视频 之后 这些文件将被独立脚本删除 问题是它还将文件写入以下目录 该软件作为系统服务运行 C Windows SysWOW64 config systemprofile Ap
  • 基于 C++ 组件的类

    Hi 我正在使用容器编写一个基于组件的类 但是在考虑了许多不同的方法之后 我找不到真正符合我想要的方法 这是总体思路的一个例子 我已经写的代码 Abstract class Component class Component public
  • Pythonlibs3 CMake 和 macOS

    更新2 将以下两行添加到我的 CMake 文件中时 成功找到了 python 3 及其库 这只在终端中工作的原因是因为 CLion 使用其捆绑版本的 CMake 3 6 3 而我的终端使用的更新版本 3 7 2 正确找到了 python F

随机推荐

  • 强化学习中的马尔可夫决策过程,常见公式回顾

    0 基础知识 0 1 贝尔曼方程 这个公式是强化学习的核心 其中 s 可以看成未来的某个状态 p s s 是指从当前状态转移到未来状态的概率 V s 代表的是未来某一个状态的价值 我们从当前状态开始 有一定的概率去到未来的所有状态 所以我们
  • Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

    Vue2 与 Vue3 的区别 Vue3由于完全由TS进行重写 在应用中对类型判断的定义和使用有很强的表现 同一对象的多个键返回值必须通过定义对应的接口 interface 来进行类型定义 要不然在 ESLint 时都会报错 Vue2 与
  • Java从入门到实战总结-3.7、XML和JSON

    Java从入门到实战总结 3 7 XML和JSON 文章目录 Java从入门到实战总结 3 7 XML和JSON 1 前言 2 XML介绍 1 XML概述 2 用途 3 处理器与应用 4 标记 Markup 与内容 content 5 标签
  • java 利用方法实现数组之间的传递

    import java util public class HelloWorld public static void main String args int arr 1 2 3 int output transform arr 运用tr
  • springboot打印启动信息

    打印启动信息 param application 应用 SneakyThrows private static void printMsg ApplicationContext application String ip InetAddre
  • vuex(4.x)

    1 简介 vuex状态管理插件 在vue最重要就是数据驱动和组件化 每个组件都有自己的data template和methods data是数据 我们也叫做状态 通过methods中方法改变状态来更新视图 在单个组件中修改状态更新视图是很方
  • vue - mvvm模式的理解?

    1 MVVM 是Model View ViewModel 的缩写 它是一种基于前端开发的架构模式 其核心是提供对View 和 ViewModel 的双向数据绑定 2 MVVM 中的核心 VM vm负责连接 View 和 Model 保证视图
  • Python如何永久修改sys.path

    Python如何永久修改sys path 起因 这两天运行需要用命令行来运行python文件 但是总是报错ModuleNotFoundError No module named xxx tf liushanlin liushanlindeM
  • 解决Fastjson的下划线与大小写映射问题

    一 问题场景 目前我有一个类如下所示 Data ToString class BTEST Long infoId Long info id 需要执行的方法如下 Test public void jsonToBean Map
  • python3使用pykeyboard和Pyhook的问题及解决

    python3 7无法import pykeyboard的原因 问题1 ModuleNotFoundError No module named windows 问题2 cant import name PyKeyboard from pkk
  • python(列表、元组、字典)详解

    文章目录 什么是列表 列表的定义 in max min sum在列表中的使用 操作列表 初识元组 元组定义 列表与元组的区别 初识字典 字典的结构与创建方法 字典的遍历 字典支持的数据类型 循环 什么是列表 列表就是队列 是各种数据类型的集
  • 关于数论中的互质数的最大不能组合数

    题意 给定A和B A和B互质 求最大不能组合数 和不能组合数的个数 基础知识 Gcd A B 1 Lcm A B AB剩余类 把所有整数划分成m个等价类 每个等价类由相互同余的整数组成任何数分成m个剩余类 分别为 mk mk 1 mk 2
  • 新论文石锤Transformer:别只看注意力,没有残差和MLP,它啥都不是

    作者 青暮 基于注意力的架构在机器学习社区中已经变得无处不在 Transformer最初在机器翻译打出名堂 随着BERT的问世几乎统治了整个NLP领域 RNN LSTM等老前辈瑟瑟发抖 GPT 3的零样本学习能力又令人不禁怀疑其智能本质 还
  • 简单几步,让Mac外接显示器更好用

    光懂得给MacBook连接外置显示器还不行 了解这几点 才能让Mac外接显示器更好用 可以在两个显示器桌面之间任意拖拽移动软件窗口 这也是双 多 显示器一个高效的地方 将外接显示器设置为最佳分辨率 MacBook连接上外接显示器后 打开 系
  • Qt之工程文件

    文章目录 1 注释 2 QT 3 模板变量 TEMPLATE 4 TARGET 5 CONFIG 6 控制输出目录 6 1 UIC DIR 6 2 RCC DIR 6 3 MOC DIR 6 4 OBJECTS DIR 6 5 DESTDI
  • linux下制作动态库

    1 动态库的介绍 动态库 也叫共享库 动态库与用户编写的程序相互独立 不被包含在用户生成的可执行文件当中 2 动态库的创建 第一步 将写好的程序编译 我们事先写好两个程序 bye c hello c 一个输出hello一个输出bye 在终端
  • Spring AOP(一)五种增强(Advice)

    AOP术语都非常抽象 结合某些小例子就会形象 具体一些 连接点 Joinpoint Spring仅支持方法的连接点 即仅能在方法调用前 方法调用后 方法抛出异常时及方法调用前后 这些程序执行点织入增强 黑客攻击系统需要找到突破口 从某种程度
  • 【安卓网络编程】Android Studio导入Volley

    在Android Studio中使用Volley框架 首先要导入Volley到项目中去 点击主界面左上角File 点击Project Structure 在Modules下 点击app 然后点击Dependencies 然后点击右边的那个
  • 企业级音视频会议实战之webrtc服务器janus品尝实战

    1 前言 之前写过单纯用webrtc和springboot实现单人 多人 屏幕分享等功能的一系列文章了 心疼各位giegie 已将例子放在下面 不麻烦你们去找了 webrtc实现视频群聊系列文章 一 之基础入门 webrtc实现视频群聊系列
  • C++ 大话设计之《访问者模式》(优缺点,设计原理,常用场景)

    访问者模式是一种行为型模式 优点 能够在不改变对象结构的情况下增加新的操作 使得操作集合可以相对独立地演化 缺点 增加新的元素类变得困难 因为每个新元素都必须被访问者类所接受 此外 如果对象结构中的元素类经常发生变化 那么使用访问者模式可能