中介者和访问者模式(行为型设计模式)的 C++ 代码示例模板

文章目录

  • 前言
  • 代码仓库
  • 中介者模式(Mediator)
  • 访问者模式(Visitor)
  • 总结
  • 参考资料
  • 作者的话

前言

中介者和访问者模式(行为型设计模式)的 C++ 代码示例模板。


代码仓库

  • yezhening/Programming-examples: 编程实例 (github.com)
  • Programming-examples: 编程实例 (gitee.com)

中介者模式(Mediator)

结构

  • 抽象同事类
  • 抽象中介者类
  • 具体中介者类 (协调交互 的对象)
  • 具体同事类 (需要交互 的对象)
  • 抽象同事类 封装 抽象中介者指针(实际上指向一个具体中介者对象)(同事 需要认识 中介者)、发送消息方法 和 接收消息方法
  • 抽象中介者类 封装 转发消息方法
  • 具体中介者类 封装 抽象同事指针(实际上指向一个具体同事对象)(中介者 需要认识 同事)
  • 具体中介者类 重写 转发消息方法 (形式上 调用 具体中介者类的 转发消息方法,实际上 调用 具体同事类的 接收消息方法(中介者 转发消息,同事 接收消息))
  • 具体同事类 重写 发送消息方法 (形式上 调用 具体同事类的 发送消息方法,实际上 调用 具体中介者类的 转发消息方法(当前同事 发送消息,委托 中介者 转发消息)) 和 接收消息方法

代码

#include <string>
#include <iostream>using std::cout;
using std::endl;
using std::string;// 注意 类的定义顺序
// 前置声明
class AbstractMediator;// 抽象同事类
class AbstractColleague
{
public:AbstractColleague(AbstractMediator *mediator) : mediator(mediator) {}// 发送消息virtual void send_message(string message) = 0;// 接收消息virtual void recv_message(string message) = 0;protected:// 抽象中介者指针(实际上指向一个具体中介者对象)(同事 需要认识 中介者)AbstractMediator *mediator;
};// 抽象中介者类
class AbstractMediator
{
public:// 转发消息virtual void forward_message(string message, AbstractColleague *colleague) = 0;
};// 具体中介者类(协调交互 的对象)
class ConcreteMediator : public AbstractMediator
{
public:// 设置同事void set_colleague_A(AbstractColleague *colleague){this->colleague_A = colleague;}void set_colleague_B(AbstractColleague *colleague){this->colleague_B = colleague;}// 转发消息void forward_message(string message, AbstractColleague *colleague) override // 形式上 调用 具体中介者类的 转发消息方法{if (colleague == this->colleague_A){this->colleague_B->recv_message(message); // 实际上 调用 具体同事类的 接收消息方法(中介者 转发消息,同事 接收消息)}else if (colleague == this->colleague_B) // 发送者 是 同事B{this->colleague_A->recv_message(message); // 接收者 是 同事A}}private:// 抽象同事指针(实际上指向一个具体同事对象)(中介者 需要认识 同事)AbstractColleague *colleague_A;AbstractColleague *colleague_B;
};// 具体同事A类(需要交互 的对象)
class ConcreteColleagueA : public AbstractColleague
{
public:ConcreteColleagueA(AbstractMediator *mediator) : AbstractColleague(mediator) {}// 发送消息void send_message(string message) override // 形式上 调用 具体同事A类的 发送消息方法{cout << "Colleague A sends message: " << message << endl;mediator->forward_message(message, this); // 实际上 调用 具体中介者类的 转发消息方法(当前同事 发送消息,委托 中介者 转发消息)。发送者 是 同事A(this)}// 接收消息void recv_message(string message) override{std::cout << "Colleague A receives message: " << message << std::endl;}
};// 具体同事类B
class ConcreteColleagueB : public AbstractColleague
{
public:ConcreteColleagueB(AbstractMediator *mediator) : AbstractColleague(mediator) {}void send_message(string message) override{cout << "Colleague B sends message: " << message << endl;mediator->forward_message(message, this);}void recv_message(string message) override{cout << "Colleague B receives message: " << message << endl;}
};// 客户端
int main()
{// 具体中介者指针(实际上指向一个具体中介者对象)ConcreteMediator *mediator = new ConcreteMediator();// 具体同事指针(实际上指向一个具体同事对象)(同事 需要认识 中介者)ConcreteColleagueA *colleague_A = new ConcreteColleagueA(mediator);ConcreteColleagueB *colleague_B = new ConcreteColleagueB(mediator);// 设置中介者的同事对象(中介者 需要认识同事)mediator->set_colleague_A(colleague_A);mediator->set_colleague_B(colleague_B);// 同事对象间 委托中介者 交互colleague_A->send_message("Hello from Colleague A");colleague_B->send_message("Hi from Colleague B");delete colleague_B;delete colleague_A;delete mediator;return 0;
}
/*
输出:
Colleague A sends message: Hello from Colleague A
Colleague B receives message: Hello from Colleague A
Colleague B sends message: Hi from Colleague B
Colleague A receives message: Hi from Colleague B
*/

访问者模式(Visitor)

结构

  • 抽象访问者类
  • 抽象元素类
  • 具体元素类
  • 具体访问者类
  • 对象结构类
  • 抽象访问者类 封装 访问方法(接收参数是具体元素指针)
  • 抽象元素类 封装 接收方法(接收参数是抽象访问者指针)
  • 具体元素类 重写 接收方法 (形式上 调用 具体元素类的 接收方法,实际上 调用 具体访问者类的 访问方法。发送参数是 this,表示 允许 访问者 访问 自身), 封装操作方法
  • 具体访问者类 重写 访问方法 (形式上 调用 具体访问者类的 访问方法,实际上 调用 具体元素类的 操作方法)
  • 对象结构类 封装 抽象元素指针(实际上指向一个具体元素对象)的集合、添加元素方法 和 接收方法 (形式上 调用 对象结构类的 接收方法,实际上 调用 具体元素类的 接收方法)

访问过程

  • 对象结构类的 接收方法,发送参数是 访问者对象(对象结构 需要 访问者访问)
  • 具体元素类的 接收方法,发送参数是 访问者对象(元素 需要 访问者访问)
  • 具体访问者类的 访问方法,发送参数是 具体元素对象(元素 允许 访问者访问)
  • 具体访问者类的 操作方法(访问者 访问 元素)

重点理解

  • 分离 稳定的数据结构(元素) 和 变化的算法(访问者)
  • 当需要添加新的操作时,只需要创建新的访问者类并实现相应的方法,而不需要修改现有的元素类

代码

#include <iostream>
#include <vector>using std::cout;
using std::endl;
using std::vector;// 注意 类的定义顺序
// 前置声明
class ConcreteElementA;
class ConcreteElementB;// 抽象访问者类
class AbstractVisitor
{
public:// 访问virtual void visit_element_A(ConcreteElementA *element) = 0; // 接收参数是具体元素指针virtual void visit_element_B(ConcreteElementB *element) = 0;
};// 抽象元素类
class AbstractElement
{
public:// 接收virtual void accept(AbstractVisitor *visitor) = 0; // 接收参数是抽象访问者指针
};// 具体元素 A 类
class ConcreteElementA : public AbstractElement
{
public:// 接收void accept(AbstractVisitor *visitor) override // 形式上 调用 具体元素类的 接收方法{visitor->visit_element_A(this);// 实际上 调用 具体访问者类的 访问方法// 发送参数是 this,表示 允许 访问者 访问 自身}// 操作void operation_A(){cout << "ConcreteElementA operation" << endl;}
};// 具体元素B类
class ConcreteElementB : public AbstractElement
{
public:void accept(AbstractVisitor *visitor) override{visitor->visit_element_B(this);}void operation_B(){cout << "ConcreteElementB operation" << endl;}
};// 具体访问者类
class ConcreteVisitor : public AbstractVisitor
{
public:// 访问void visit_element_A(ConcreteElementA *element) override // 形式上 调用 具体访问者类的 访问方法{cout << "ConcreteVisitor visits ConcreteElementA" << endl;element->operation_A(); // 实际上 调用 具体元素类的 操作方法}void visit_element_B(ConcreteElementB *element) override{cout << "ConcreteVisitor ConcreteElementB" << endl;element->operation_B();}
};// 当需要添加新的操作时,只需要创建新的访问者类并实现相应的方法,而不需要修改现有的元素类
// 具体访问者新类
class ConcreteVisitorNew : public AbstractVisitor
{
public:// 访问// 新的操作void visit_element_A(ConcreteElementA *element) override{cout << "ConcreteVisitorNew visits ConcreteElementA" << endl;element->operation_A();}void visit_element_B(ConcreteElementB *element) override{cout << "ConcreteVisitorNew ConcreteElementB" << endl;element->operation_B();}
};// 对象结构类
class ObjectStructure
{
public:// 添加元素void add_element(AbstractElement *element){this->element_vec.push_back(element);}// 移除元素// 接收void accept(AbstractVisitor *visitor) // 形式上 调用 对象结构类的 接收方法{for (AbstractElement *element : this->element_vec){element->accept(visitor); // 实际上 调用 具体元素类的 接收方法}}private:// 抽象元素指针(实际上指向一个具体元素对象)的集合vector<AbstractElement *> element_vec;
};// 客户端
int main()
{// 具体元素对象ConcreteElementA element_A;ConcreteElementB element_B;// 对象结构对象ObjectStructure object_structure;object_structure.add_element(&element_A); // 对象结构 添加元素object_structure.add_element(&element_B);// 具体访问者对象ConcreteVisitor visitor;object_structure.accept(&visitor); // 对象结构 接收 访问者的访问// 访问过程:// object_structure.accept(&visitor); ->// 对象结构类的 接收方法,发送参数是 访问者对象(对象结构 需要 访问者访问)// element->accept(visitor); ->// 具体元素类的 接收方法,发送参数是 访问者对象(元素 需要 访问者访问)// visitor->visit_element_A(this);// 具体访问者类的 访问方法,发送参数是 具体元素对象(元素 允许 访问者访问)// element->operation_A();// 具体访问者类的 操作方法(访问者 访问 元素)// 具体访问者新对象ConcreteVisitorNew visitor_new;object_structure.accept(&visitor_new);return 0;
}
/*
输出:
ConcreteVisitor visits ConcreteElementA
ConcreteElementA operation
ConcreteVisitor ConcreteElementB
ConcreteElementB operation
ConcreteVisitorNew visits ConcreteElementA
ConcreteElementA operation
ConcreteVisitorNew ConcreteElementB
ConcreteElementB operation
*/

总结

中介者和访问者模式(行为型设计模式)的 C++ 代码示例模板。


参考资料

  • 行为型设计模式总结_设计模式行为型模式的设计与实现心得体会-CSDN博客

作者的话

  • 感谢参考资料的作者/博主
  • 作者:夜悊
  • 版权所有,转载请注明出处,谢谢~
  • 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
  • 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
  • 文章在认识上有错误的地方, 敬请批评指正
  • 望读者们都能有所收获

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

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

相关文章

HarmonyOS应用程序包-(下)

HarmonyOS应用程序包-(下) 1.多HAP的开发调试与发布部署流程 多HAP的开发调试与发布部署流程如下图所示。 图1 多HAP的开发调试与发布部署流程 开发 开发者通过DevEco Studio工具按照业务的需要创建多个Module&#xff0c;在相应的Module中完成自身业务的开发。 调试 通过…

C++归并排序详解以及代码实现

1. 介绍 归并排序&#xff08;Merge Sort&#xff09;是一种采用分治法&#xff08;Divide and Conquer&#xff09;策略的排序算法。该算法首先将已有序的子序列合并&#xff0c;得到完全有序的序列。在归并排序中&#xff0c;合并操作是将两个有序表合并成一个有序表的过程。…

echarts实现七天天气预报

效果图 实现代码 const imglist {"晴": data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAAXNSR0IArs4c6QAAByJJREFUaEO9Wl1rFGcUfs67u/nYbOIXJlGopBTx27aQWGOwSMS75sao2BtBQVD/gWCJouA/sIWCBW8M1nqjd1IplW5DYqLWEUoSi9iEjHaJmaz2d05ZWd2Nj…

KingbaseV8R6单实例定时全量备份步骤

此场景为单机数据库节点内部备份&#xff0c;方便部署和操作&#xff0c;但备份REPO与数据库实例处于同一个物理主机&#xff0c;冗余度较低。 前期准备 配置ksql免密登录(必须) 在Kingbase数据库运行维护中&#xff0c;经常用到ksql工具登录数据库&#xff0c;本地免密登录…

基于OpenCV的图像颜色与形状识别的原理

基于 OpenCV 的图像颜色与形状识别是通过以下原理实现的&#xff1a; 图像预处理&#xff1a;首先&#xff0c;将彩色图像转换为灰度图像。这样做是因为在灰度图像中&#xff0c;每个像素只有一个颜色通道&#xff0c;可以更方便地进行后续处理。 阈值分割&#xff1a;对灰度图…

Linux系统编程(六):进程(下)

参考引用 UNIX 环境高级编程 (第3版)嵌入式Linux C应用编程-正点原子 1. 进程与程序 1.1 main() 函数由谁调用&#xff1f; C 语言程序总是从 main 函数开始执行int main(void) int main(int argc, char *argv[]) // 如果需要向应用程序传参&#xff0c;则选择该种写法操作系…

C++ 比 C语言增加的新特性 2

1.C新增了带默认值参数的函数 1.1 格式 格式&#xff1a;返回值 函数名&#xff08;参数1初始值1&#xff0c;..........&#xff09;{} 例如&#xff1a;void function&#xff08;int a10&#xff09;{} 调用&#xff1a;不需要更改参数的值&#xff1a;function&#x…

基于SSM和微信小程序的高校体育场管理系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于SSM和微信小程序的高校体育场管理系…

文本编辑器:Sublime Text (安装+汉化)

下载 Sublime Text - Text Editing, Done Righthttps://www.sublimetext.com/Sublime Text官网 支持mac&#xff0c;Linux&#xff0c;Windows 安装 选择安装路径 next install 选择安装位置安装就行了 汉化 进入了主界面按 CTRLshiftp 输入install 选择第一个 弹窗就按确…

服务器扩容未生效、不成功:解决方法

记一次解决服务器扩容未生效的解决办法 老板&#xff1a;失忆啊&#xff0c;我花钱给服务器扩容了10000000G&#xff0c;但是数据库和mq都还是用不了&#xff0c;到底是不是服务器磁盘满了&#xff0c;你到底有没有查一下什么原因导致服务用不了啊。 失忆&#xff1a;老板您确…

概率论1:下象棋问题(3.5)

每日小语 时刻望着他人的眼色行事&#xff0c;是腾飞不了的。自己怎么想就积极地去做&#xff0c;这是需要胆量的。——广中平佑 题目 甲、乙二人下象棋&#xff0c; 每局甲胜的概率为a,乙胜的概率为b. 为简化问题&#xff0c;设没有和局的情况&#xff0c;这意味着a b1. 设想…

VR全景对普通人的生活有哪些好处?

许多普通人对VR全景还全然没有概念&#xff0c;这是因为VR全景虽然一直在快速发展&#xff0c;但目前为止也不过几年而已&#xff0c;但这发展的几年同样为我们普通人的生活带来了切实的改变和便利。VR全景技术为人们带来了沉浸感和真实感的体验&#xff0c;让我们感受到迥异于…

第十四章 集合(Set)

一、Set 接口&#xff08;P518&#xff09; 1. Set 接口基本介绍 &#xff08;1&#xff09;无序&#xff08;添加和取出的顺序不一致&#xff09;&#xff0c;没有索引。 &#xff08;2&#xff09;不允许重复元素&#xff0c;所以最多包含一个 null。 2. Set 接口的常用方法…

数据结构:KMP算法

1.何为KMP算法 KMP算法是由Knuth、Morris和Pratt三位学者发明的&#xff0c;所以取了三位学者名字的首字母&#xff0c;叫作KMP算法。 2.KMP的用处 KMP主要用于字符串匹配的问题&#xff0c;主要思想是当出现字符串不匹配时&#xff0c;我们可以知道一部分之前已经匹配过的的文…

【期刊周报1】医学好刊(SCI/SSCI/EI),含Top,领域广,接收快!

为了向广大学者朋友提供更优质的选刊服务&#xff0c;提高选刊质量&#xff0c;我处现开设周报专栏&#xff0c;以罗列我处合作的优质期刊~ 本期&#xff0c;小编给大家推荐的是医学领域相关的热门期刊&#xff0c;接收领域广&#xff0c;无预警&#xff0c;且在最新检索目录内…

Python遥感影像深度学习指南(2)-在 PyTorch 中创建自定义数据集和加载器

在上一篇 文章中,我们Fast.ai 在卫星图像中检测云轮廓,检测物体轮廓被称为语义分割。虽然我们用几行代码就能达到 96% 的准确率,但该模型无法考虑数据集中提供的所有输入通道(红、绿、蓝和近红外)。问题在于,深度学习框架(如 Keras、Fast.ai 甚至 PyTorch)中的大多数语…

油烟净化器如何做到高效净化?科技力量,清新餐饮生活

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们。 油烟净化器的出现&#xff0c;为我们的餐饮生活注入了一抹清新的色彩。然而&#xff0c;它究竟是如何工作的&#xff1f;为何能…

【开题报告】基于SSM的健康饮食系统设计与实现

1.研究背景 如今&#xff0c;随着人们生活水平的提高和健康意识的增强&#xff0c;越来越多的人开始关注自己的饮食习惯&#xff0c;并希望通过合理的饮食来维持身体健康。然而&#xff0c;对于许多人来说&#xff0c;了解和选择合适的饮食方式并不容易。传统的饮食指导往往比…

【并发设计模式】聊聊Immutability模式利用不变性解决并发问题

上一篇文章&#xff0c;我们介绍了如何利用二阶段停止协议进行优雅停止线程和线程池&#xff0c;本篇介绍在并发编程中数据安全性&#xff0c;我们知道针对于数据的操作&#xff0c;读和写(添加、删除、修改), 在并发线程读写的时候&#xff0c;变量不加锁的情况下&#xff0c;…

redis哨兵+redis主从复制(在虚拟机centos的docker下)

1.安装docker Docker安装(CentOS)简单使用-CSDN博客 2.redis主从复制 redis主从复制(在虚拟机centos的docker下)-CSDN博客 3.编辑3个redis配置 cd /etc mkdir redis-sentinel cd redis-sentinel/ wget http://download.redis.io/redis-stable/sentinel.confcp sentinel.co…