设计模式---中介者模式
设计模式---中介者模式
- 定义与设计思路
- 中介者模式的引入:机场控制塔
- 中介者模式的设计框架
定义与设计思路
-
定义:用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,属于行为型模式。
-
设计思路:用一个中介对象来封装一系列的对象交互操作,中介者模式使得对象之间不需要显示的相互引用,从而使得系统或模块内部相互解耦,而且可以独立的改变它们至今的交互
中介者模式的引入:机场控制塔
想象一个繁忙的机场,有许多飞机在同一时间内起飞和降落。如果每架飞机都直接与其他飞机通信,协商谁该先起飞、谁该先降落,整个机场的调度将变得非常复杂。每架飞机都要知道其他所有飞机的状态、飞行路线、优先级等,导致信息的传递和处理变得混乱而低效。
问题:飞机之间的复杂通信
直接通信导致混乱: 每架飞机要知道并与其他所有飞机通信,管理起飞、降落的顺序会变得非常困难且危险。
- 维护成本高: 增加或移除一架飞机,所有飞机的通信方式都需要更新,增加了维护的难度。
- 耦合度过高: 每架飞机相互依赖,任何一个飞机的变动可能会影响整个系统的稳定性。
中介模式解决问题:引入机场控制塔
为了简化调度过程,机场引入了控制塔作为中介者。控制塔的职责是协调所有飞机的起飞和降落,保证每架飞机都能安全有- 序地运行。这样,每架飞机只需要与控制塔通信,而不需要关心其他飞机的具体状态。
- 控制塔(中介者): 控制飞机的起飞和降落顺序,管理它们的路线和时间安排。
- 飞机(同事类): 负责向控制塔报告自己的状态(如准备起飞、准备降落等),并接收控制塔的指令(如可以起飞或等待)。
中介模式的作用:
去耦合: 飞机之间不再直接通信,只需要和控制塔交互,这大大简化了飞机之间的相互依赖。
集中控制: 所有的调度逻辑都集中在控制塔中,便于统一管理,维护起来更加简单。
易于扩展: 新的飞机可以轻松加入机场系统,只需要和控制塔通信,而不需要重新调整其他飞机的通信逻辑。
中介者模式的设计框架
需要一个中介者类和同事类,目的是通过中介者类对象对象完成同事类实例之间的信息交互。其中,中介者类中需要有一个储存注册进来的同事对象的列表、发送消息的接口(协助同事实例完成消息的转发)、注册函数(完成同事实例的注册)。所有的同事类实例包含一个发布消息接口、接收消息的接口(接收中介转发的消息),另外包含一个中介实例成员变量(用于完成消息的转发的接口对象)。
中介模式的关键要素:
- 中介者(Mediator): 中介者负责定义对象之间的通信接口,具体的通信逻辑则由具体的中介者实现。
- 具体中介者(Concrete Mediator): 这是中介者的具体实现,它维护所有参与者对象,并处理这些对象之间的通信。
- 同事类(Colleague): 这些是参与通信的对象,它们通过中介者进行相互通信,而不是直接引用其他同事对象。
#include <bits/stdc++.h>//
//中介者模式
//关键代码:对象 Colleague 之间的通信封装到一个类中单独处理
//class Mediator;//抽象人(同事类)
class Person
{
protected:std::shared_ptr<Mediator> m_mediator; //中介类实例
public:Person(const std::shared_ptr<Mediator> pMediator) : m_mediator(pMediator) {}//虚析构函数virtual ~Person() = default;//向中介发送信息virtual void SendMessage(const std::string &message) = 0;//从中介获取信息//message 中介向该对象发送的信息/从中介获取的信息virtual void GetMessage(const std::string &message) = 0;
};//抽象中介机构
class Mediator
{
public:virtual ~Mediator() = default;//由于后面this指针的原因,此处未采用智能指针virtual void Send(std::string message, const Person *from_person) const = 0;virtual void Register(std::shared_ptr<Person> pPerson) = 0;
};//租房者A
class RenterA : public Person
{
public:RenterA(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}void SendMessage(const std::string &message) override{m_mediator->Send(message, this);}void GetMessage(const std::string &message) override{std::cout << "租房者A收到信息" << message << std::endl;;}
};//租房者B
class RenterB : public Person
{
public:RenterB(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}void SendMessage(const std::string &message) override{m_mediator->Send(message, this);}void GetMessage(const std::string &message) override{std::cout << "租房者B收到信息" << message << std::endl;;}
};//房东
class Landlord : public Person
{
public:Landlord(const std::shared_ptr<Mediator> mediator) : Person(mediator) {}void SendMessage(const std::string &message) override{m_mediator->Send(message, this);}void GetMessage(const std::string &message) override{std::cout << "房东收到信息:" << message << std::endl;;}
};//房屋中介
class HouseMediator : public Mediator
{
private://也可以采用多个list,将多个房东放入一个list,将多个求租者放入一个liststd::vector<std::shared_ptr<Person>> m_pPersonList;
public:void Register(const std::shared_ptr<Person> pPerson) override{//没有添加该同事,则添加进去auto iter = m_pPersonList.begin();for (; iter != m_pPersonList.end(); ++iter){if (*iter == pPerson)break;}if (iter == m_pPersonList.end())m_pPersonList.emplace_back(pPerson);}void Send(std::string message, const Person *from_person) const override{//接收消息的对象为该对象的对应对象for (const auto item:m_pPersonList){//此处采用typeid,而非直接判断指针是否相等为同一个对象.if (typeid(*item.get()) != typeid(*from_person)){item->GetMessage(message);}}}
};int main() {std::shared_ptr<Mediator> pHouseMediator = std::make_shared<HouseMediator>();std::shared_ptr<Person> pRenterA = std::make_shared<RenterA>(pHouseMediator);std::shared_ptr<Person> pRenterB = std::make_shared<RenterB>(pHouseMediator);std::shared_ptr<Person> pLandlord = std::make_shared<Landlord>(pHouseMediator);pHouseMediator->Register(pRenterA);pHouseMediator->Register(pRenterB);pHouseMediator->Register(pLandlord);pLandlord->SendMessage("出租房子:中山路100号,50平米,2000元一个月");//所有的求租者将会收到该消息std::cout << std::string(50, '-') << std::endl;pRenterA->SendMessage("我想在中山路附近租套房子,价格1500元一个月");//所有的房东将会收到该消息return 0;
}
输出
租房者A收到信息出租房子:中山路100号,50平米,2000元一个月
租房者B收到信息出租房子:中山路100号,50平米,2000元一个月
--------------------------------------------------
租房者B收到信息我想在中山路附近租套房子,价格1500元一个月
房东收到信息:我想在中山路附近租套房子,价格1500元一个月
发送的消息通过中介转发给租房者,租房者发送的消息通过中介转发给
感谢大佬的讲解
https://blog.csdn.net/leonardohaig/article/details/109963550
相关文章:
设计模式---中介者模式
设计模式---中介者模式 定义与设计思路中介者模式的引入:机场控制塔中介者模式的设计框架 定义与设计思路 定义:用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用,从而使其耦合松散,而且可以独立地改变它们之间…...
六氟化硫密度微水在线监测配套5孔M12格兰头航空插头插座
我们将为大家介绍如何使用六氟化硫密度微水在线监测配套5孔M12格兰头连接器。在本教程中,我们将向您展示简单易懂的步骤,让您轻松掌握。 所需材料: 1. 六氟化硫密度微水在线监测器 2. 5孔M12格兰头连接器 3. 电源线 4. 符合要求的电缆 5…...
linux -L4.linux 暂停和启动进程
接第3课,L3 第3课-查看进程 通过端口号,查看对应的进程 netstat -tulnp | grep :9513暂停这个进程 Kill -STOP 5376重启这个进程 Kill -CONT 5376要查看特定PID对应的端口,你可以使用netstat命令结合grep工具来过滤输出。以下是一个基于L…...
Java多线程编程-基础篇
多线程相关的概念 并发 并发是指在同一时间段内,两个或多个任务在同一个处理器上交替执行,使得在宏观上看起来像是同时进行。并发是通过快速切换任务来模拟同时执行的效果,实际上在任何一个时刻点上只有一个任务在执行。 也就是说࿰…...
【极限、数学】 NOIP 2018 提高组初赛试题 第 7 题详解(线段长度期望)
在一条长度为 1 1 1 的线段上随机取两个点,则以这两个点为端点的线段的期望长度是( )。 考虑将一个线段上平均分布有 n ( n ≥ 2 ) n(n\geq 2) n(n≥2) 个节点,其中首尾均有一个节点,那么我们就将一个线段均分为 n…...
《论网络安全体系设计》写作框架,软考高级系统架构设计师
论文真题 随着社会信息化的普及,计算机网络已经在各行各业得到了广泛的应用。目前,绝大多数业务处理几乎完全依赖计算机和网络执行,各种重要数据如政府文件、工资档案、财务账目和人事档案等均依赖计算机和网络进行存储与传输。另一方面&…...
这款开源的通用PDF处理神器,功能炸裂!
今天分享一款以PDF为中心的多功能办公学习工具箱软件,包含四大板块功能:PDF实用工具箱、Anki制卡神器、Anki最强辅助、视频笔记神器,软件功能众多且强大,熟练运用可以大幅提高办公和学习效率,绝对是您不可多得的效率神…...
RabbitMQ延迟消息——DelayExchange插件
什么是死信以及死信交换机 当一个队列中的消息满足下列情况之一时,可以成为死信: 1. 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false 2. 消息是一个过期消息,超时无人消费 3. 要投递的队列消…...
【系统规划与管理师】【案例分析】【考点】【答案篇】第5章 IT服务部署实施
【问题篇】☞【系统规划与管理师】【案例分析】【考点】【问题篇】第5章 IT服务部署实施 【移动端浏览】☞【系统规划与管理师】【案例分析】【模拟考题】章节考题汇总(第5章)(答案篇)(共24个知识点) 第5章…...
华为云服务器的数据库部署及管理
不管是终端数据上报到服务器进行存储,还是客户端的动态请求都需要用到数据库,因此这里对数据库的使用进行了一些记录,租用的是华为云的ECS弹性服务器(Ubuntu18)。下面以网页登录的账号信息Acount为例。 一、Mysql的安装…...
C#【必备技能篇】替换一个字节(byte)中连续几位(bit)的内容
文章目录 一、一个示例二、通用方法 一、一个示例 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp1 {class Program{static void Main(string[] args){Method1();}public static…...
roboguide将tp程序转化为LS文本格式的方法
不同的软件版本可能操作不同,但是仍然可以参考文章中的办法。 我使用的版本如图所示: 1.首先,打开任意一个工程,如果没有,可以打开自带的示例。 如图,我打开了自带的示例,在帮助文档中可以找到…...
基于SpringBoot+Vue+MySQL的流浪猫狗宠物救助救援网站管理系统
系统展示 用户前台界面 管理员后台界面 系统背景 在当今社会,随着宠物数量的激增及人们关爱动物意识的提升,流浪猫狗问题日益严峻。为解决这一问题,构建一套高效、便捷的流浪猫狗宠物救助救援网站管理系统显得尤为重要。本系统基于SpringBoot…...
I/O 多路复用:`select`、`poll`、`epoll` 和 `kqueue` 的区别与示例
I/O 多路复用是指在一个线程内同时监控多个文件描述符(File Descriptor, FD),以便高效地处理多个 I/O 事件。在 UNIX/Linux 和 BSD 系统中,select、poll、epoll、kqueue 都是实现 I/O 多路复用的系统调用。它们各有特点࿰…...
大数据之Flink(三)
9.3、转换算子 9.3.1、基本转换算子 9.3.1.1、映射map 一一映射 package transform;import bean.WaterSensor; import org.apache.flink.streaming.api.datastream.DataStreamSource; import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; impor…...
【HCIA-Datacom】IPv4地址介绍
| | 👉个人主页:Reuuse 希望各位多多支持!❀ | 👉HCIA专栏博客 | 最后如果对你们有帮助的话希望有一个大大的赞! | ⭐你们的支持是我最大的动力!⭐ | 目录 IPv4地址定义IPv4地址分类方式二级目录三级目录 I…...
maven父子工程多模块如何管理统一的版本号?
1.为什么要统一管理? maven父子工程多模块,每个模块还都可以独立存在,子模块往往通常希望和父工程保持一样的版本,如果每个工程单独定义版本号,后期变更打包也非常麻烦,如何维护一个全局的版本号呢&#x…...
JavaScript --函数的作用域(全局和局部)
全局作用域 全局作用域,就算不在一个script标签也能调用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta nam…...
贪吃蛇项目实现(C语言)——附源码
前言 贪吃蛇是一款十分经典的游戏,其通过控制贪吃蛇的上下左右移动来吃食物,延长自己的身体,也会因为撞到墙体和自身而死亡。下面我们通过C语言来实现贪吃蛇。 1.技术要点 C语言枚举,结构体,链表,动态内…...
【C++】42道面试经典问题总结
C this指针是干什么用的? 假如一个类型定义了很多对象,类里面有很多定义的私有成员变量,共享一套成员方法。通过this指针这可以区分方法、变量是操作的哪个对象的。 C的new和delete,new[]和delete[]可以混用吗? 一般来…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
