当前位置: 首页 > news >正文

设计模式---中介者模式

设计模式---中介者模式

  • 定义与设计思路
  • 中介者模式的引入:机场控制塔
  • 中介者模式的设计框架

定义与设计思路

  • 定义:用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,属于行为型模式。

  • 设计思路:用一个中介对象来封装一系列的对象交互操作,中介者模式使得对象之间不需要显示的相互引用,从而使得系统或模块内部相互解耦,而且可以独立的改变它们至今的交互

中介者模式的引入:机场控制塔

想象一个繁忙的机场,有许多飞机在同一时间内起飞和降落。如果每架飞机都直接与其他飞机通信,协商谁该先起飞、谁该先降落,整个机场的调度将变得非常复杂。每架飞机都要知道其他所有飞机的状态、飞行路线、优先级等,导致信息的传递和处理变得混乱而低效。

问题:飞机之间的复杂通信
直接通信导致混乱: 每架飞机要知道并与其他所有飞机通信,管理起飞、降落的顺序会变得非常困难且危险。

  • 维护成本高: 增加或移除一架飞机,所有飞机的通信方式都需要更新,增加了维护的难度。
  • 耦合度过高: 每架飞机相互依赖,任何一个飞机的变动可能会影响整个系统的稳定性。

中介模式解决问题:引入机场控制塔
为了简化调度过程,机场引入了控制塔作为中介者。控制塔的职责是协调所有飞机的起飞和降落,保证每架飞机都能安全有- 序地运行。这样,每架飞机只需要与控制塔通信,而不需要关心其他飞机的具体状态。

  • 控制塔(中介者): 控制飞机的起飞和降落顺序,管理它们的路线和时间安排。
  • 飞机(同事类): 负责向控制塔报告自己的状态(如准备起飞、准备降落等),并接收控制塔的指令(如可以起飞或等待)。

中介模式的作用:
去耦合: 飞机之间不再直接通信,只需要和控制塔交互,这大大简化了飞机之间的相互依赖。
集中控制: 所有的调度逻辑都集中在控制塔中,便于统一管理,维护起来更加简单。
易于扩展: 新的飞机可以轻松加入机场系统,只需要和控制塔通信,而不需要重新调整其他飞机的通信逻辑。

中介者模式的设计框架

需要一个中介者类和同事类,目的是通过中介者类对象对象完成同事类实例之间的信息交互。其中,中介者类中需要有一个储存注册进来的同事对象的列表、发送消息的接口(协助同事实例完成消息的转发)、注册函数(完成同事实例的注册)。所有的同事类实例包含一个发布消息接口、接收消息的接口(接收中介转发的消息),另外包含一个中介实例成员变量(用于完成消息的转发的接口对象)。

中介模式的关键要素:

  • 中介者(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

相关文章:

设计模式---中介者模式

设计模式---中介者模式 定义与设计思路中介者模式的引入&#xff1a;机场控制塔中介者模式的设计框架 定义与设计思路 定义&#xff1a;用一个中介对象来封装一系列对象交互。中介者使各对象不需要相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间…...

六氟化硫密度微水在线监测配套5孔M12格兰头航空插头插座

我们将为大家介绍如何使用六氟化硫密度微水在线监测配套5孔M12格兰头连接器。在本教程中&#xff0c;我们将向您展示简单易懂的步骤&#xff0c;让您轻松掌握。 所需材料&#xff1a; 1. 六氟化硫密度微水在线监测器 2. 5孔M12格兰头连接器 3. 电源线 4. 符合要求的电缆 5…...

linux -L4.linux 暂停和启动进程

接第3课&#xff0c;L3 第3课-查看进程 通过端口号&#xff0c;查看对应的进程 netstat -tulnp | grep :9513暂停这个进程 Kill -STOP 5376重启这个进程 Kill -CONT 5376要查看特定PID对应的端口&#xff0c;你可以使用netstat命令结合grep工具来过滤输出。以下是一个基于L…...

Java多线程编程-基础篇

多线程相关的概念 并发 并发是指在同一时间段内&#xff0c;两个或多个任务在同一个处理器上交替执行&#xff0c;使得在宏观上看起来像是同时进行。并发是通过快速切换任务来模拟同时执行的效果&#xff0c;实际上在任何一个时刻点上只有一个任务在执行。 也就是说&#xff0…...

【极限、数学】 NOIP 2018 提高组初赛试题 第 7 题详解(线段长度期望)

在一条长度为 1 1 1 的线段上随机取两个点&#xff0c;则以这两个点为端点的线段的期望长度是&#xff08; &#xff09;。 考虑将一个线段上平均分布有 n ( n ≥ 2 ) n(n\geq 2) n(n≥2) 个节点&#xff0c;其中首尾均有一个节点&#xff0c;那么我们就将一个线段均分为 n…...

《论网络安全体系设计》写作框架,软考高级系统架构设计师

论文真题 随着社会信息化的普及&#xff0c;计算机网络已经在各行各业得到了广泛的应用。目前&#xff0c;绝大多数业务处理几乎完全依赖计算机和网络执行&#xff0c;各种重要数据如政府文件、工资档案、财务账目和人事档案等均依赖计算机和网络进行存储与传输。另一方面&…...

这款开源的通用PDF处理神器,功能炸裂!

今天分享一款以PDF为中心的多功能办公学习工具箱软件&#xff0c;包含四大板块功能&#xff1a;PDF实用工具箱、Anki制卡神器、Anki最强辅助、视频笔记神器&#xff0c;软件功能众多且强大&#xff0c;熟练运用可以大幅提高办公和学习效率&#xff0c;绝对是您不可多得的效率神…...

RabbitMQ延迟消息——DelayExchange插件

什么是死信以及死信交换机 当一个队列中的消息满足下列情况之一时&#xff0c;可以成为死信&#xff1a; 1. 消费者使用basic.reject或 basic.nack声明消费失败&#xff0c;并且消息的requeue参数设置为false 2. 消息是一个过期消息&#xff0c;超时无人消费 3. 要投递的队列消…...

【系统规划与管理师】【案例分析】【考点】【答案篇】第5章 IT服务部署实施

【问题篇】☞【系统规划与管理师】【案例分析】【考点】【问题篇】第5章 IT服务部署实施 【移动端浏览】☞【系统规划与管理师】【案例分析】【模拟考题】章节考题汇总&#xff08;第5章&#xff09;&#xff08;答案篇&#xff09;&#xff08;共24个知识点&#xff09; 第5章…...

华为云服务器的数据库部署及管理

不管是终端数据上报到服务器进行存储&#xff0c;还是客户端的动态请求都需要用到数据库&#xff0c;因此这里对数据库的使用进行了一些记录&#xff0c;租用的是华为云的ECS弹性服务器&#xff08;Ubuntu18&#xff09;。下面以网页登录的账号信息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文本格式的方法

不同的软件版本可能操作不同&#xff0c;但是仍然可以参考文章中的办法。 我使用的版本如图所示&#xff1a; 1.首先&#xff0c;打开任意一个工程&#xff0c;如果没有&#xff0c;可以打开自带的示例。 如图&#xff0c;我打开了自带的示例&#xff0c;在帮助文档中可以找到…...

基于SpringBoot+Vue+MySQL的流浪猫狗宠物救助救援网站管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当今社会&#xff0c;随着宠物数量的激增及人们关爱动物意识的提升&#xff0c;流浪猫狗问题日益严峻。为解决这一问题&#xff0c;构建一套高效、便捷的流浪猫狗宠物救助救援网站管理系统显得尤为重要。本系统基于SpringBoot…...

I/O 多路复用:`select`、`poll`、`epoll` 和 `kqueue` 的区别与示例

I/O 多路复用是指在一个线程内同时监控多个文件描述符&#xff08;File Descriptor, FD&#xff09;&#xff0c;以便高效地处理多个 I/O 事件。在 UNIX/Linux 和 BSD 系统中&#xff0c;select、poll、epoll、kqueue 都是实现 I/O 多路复用的系统调用。它们各有特点&#xff0…...

大数据之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地址介绍

| | &#x1f449;个人主页&#xff1a;Reuuse 希望各位多多支持&#xff01;❀ | &#x1f449;HCIA专栏博客 | 最后如果对你们有帮助的话希望有一个大大的赞&#xff01; | ⭐你们的支持是我最大的动力&#xff01;⭐ | 目录 IPv4地址定义IPv4地址分类方式二级目录三级目录 I…...

maven父子工程多模块如何管理统一的版本号?

1.为什么要统一管理&#xff1f; maven父子工程多模块&#xff0c;每个模块还都可以独立存在&#xff0c;子模块往往通常希望和父工程保持一样的版本&#xff0c;如果每个工程单独定义版本号&#xff0c;后期变更打包也非常麻烦&#xff0c;如何维护一个全局的版本号呢&#x…...

JavaScript --函数的作用域(全局和局部)

全局作用域 全局作用域&#xff0c;就算不在一个script标签也能调用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta nam…...

贪吃蛇项目实现(C语言)——附源码

前言 贪吃蛇是一款十分经典的游戏&#xff0c;其通过控制贪吃蛇的上下左右移动来吃食物&#xff0c;延长自己的身体&#xff0c;也会因为撞到墙体和自身而死亡。下面我们通过C语言来实现贪吃蛇。 1.技术要点 C语言枚举&#xff0c;结构体&#xff0c;链表&#xff0c;动态内…...

【C++】42道面试经典问题总结

C this指针是干什么用的&#xff1f; 假如一个类型定义了很多对象&#xff0c;类里面有很多定义的私有成员变量&#xff0c;共享一套成员方法。通过this指针这可以区分方法、变量是操作的哪个对象的。 C的new和delete&#xff0c;new[]和delete[]可以混用吗&#xff1f; 一般来…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...