设计模式15:中介者模式

 系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客

1.概述

     中介者模式(Mediator Pattern)是一种行为设计模式,旨在通过一个中介对象来封装一系列对象之间的交互方式,从而减少这些对象间的直接依赖。在该模式下,各个组件(同事)不再直接相互通信,而是通过中介者进行间接沟通,这极大地降低了系统的耦合度。具体来说,中介者定义了同事类之间的通信接口,并负责协调同事对象之间的交互逻辑。每个同事类都知道其对应的中介者对象,但并不直接与其他同事类交互。

2.结构与实现

结构:

  • Mediator(抽象中介者):定义同事类之间的通信接口。
  • ConcreteMediator(具体中介者):实现了抽象中介者的接口,并协调各同事对象之间的交互。
  • Colleague Class(抽象同事类):每个同事类都知道其对应的中介者对象,并且可以通过中介者发送消息给其他同事。
  • ConcreteColleague(具体同事类):实现了抽象同事类,负责发送和接收消息。

实现:

假设我们要创建一个简单的聊天应用程序,用户之间通过ChatRoom(中介者)进行交流。

代码目录结构为:

首先,定义ChatRoom作为抽象中介者:

ChatRoom.h:

#ifndef CHATROOM_H
#define CHATROOM_H#include <QString>class User; // 前向声明User类,避免循环依赖// 抽象中介者:定义同事类之间的通信接口。
class ChatRoom {
public:virtual void sendMessage(const QString& message, User* user) = 0; // 发送消息的纯虚函数
};#endif // CHATROOM_H

ConcreteChatRoom.h

#ifndef CONCRETECHATROOM_H
#define CONCRETECHATROOM_H#include "ChatRoom.h"
#include <QList> // Qt容器类,用于存储用户列表
#include "User.h"// 具体中介者:实现了抽象中介者的接口,并协调各同事对象之间的交互。
class ConcreteChatRoom : public ChatRoom {
private:QList<User*> users; // 存储所有用户的列表
public:// 添加用户到聊天室中void addUser(User* user) {users.append(user);}// 实现发送消息的功能void sendMessage(const QString& message, User* user) override;
};#endif // CONCRETECHATROOM_H

ConcreteChatRoom.cpp

#include "ConcreteChatRoom.h"
#include "User.h"
#include <QDebug>// 实现sendMessage方法,遍历所有用户并转发消息给其他用户(除了发送者)
void ConcreteChatRoom::sendMessage(const QString& message, User* user)
{// 遍历所有用户for (User* u : users){if(u != user) { // 如果不是消息的发送者,则转发消息u->receiveMessage(message); // 调用接收消息的方法}}
}

User.h

#ifndef USER_H
#define USER_H#include <QString>
#include "ChatRoom.h" // 包含中介者接口// 抽象同事类:每个同事类都知道其对应的中介者对象,并且可以通过中介者发送消息给其他同事。
class User {
protected:ChatRoom* chatroom; // 指向中介者的指针QString name; // 用户名
public:// 构造函数,初始化中介者和用户名User(ChatRoom* chatroom, const QString& name): chatroom(chatroom), name(name) {}// 发送消息的方法virtual void sendMessage(const QString& message);// 接收消息的方法virtual void receiveMessage(const QString& message);// 获取用户名的方法QString getName() const { return name; }
};#endif // USER_H

User.cpp

#include "User.h"
#include "ConcreteChatRoom.h" // 包含具体中介者的头文件
#include <QDebug>// 发送消息的实现
void User::sendMessage(const QString& message) {qDebug() << getName() << " sends: " << message; // 打印发送者信息chatroom->sendMessage(message, this); // 通过中介者发送消息
}// 接收消息的实现
void User::receiveMessage(const QString& message) {qDebug() << getName() << " receives: " << message; // 打印接收者信息
}

main.cpp:

#include <QCoreApplication>
#include "ConcreteChatRoom.h" // 包含具体中介者
#include "User.h" // 包含同事类int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建一个具体的中介者实例ConcreteChatRoom chatRoom;// 创建两个用户并关联到同一个中介者User user1(&chatRoom, "Alice");User user2(&chatRoom, "Bob");User user3(&chatRoom, "Tom");// 将用户添加到聊天室中chatRoom.addUser(&user1);chatRoom.addUser(&user2);chatRoom.addUser(&user3);// 用户发送消息user1.sendMessage("Hello Bob!");//user2.sendMessage("Hi Alice!");return a.exec();
}

运行效果:

"Alice"  sends:  "Hello Bob!"
"Bob"  receives:  "Hello Bob!"
"Tom"  receives:  "Hello Bob!"

3.应用

中介者模式非常适合用于以下场景:

  • GUI框架中,例如Qt,其中各种控件可能需要相互通讯但又不希望直接依赖对方。
  • 多模块或分布式系统中,各个模块或节点之间的通信可以由中介者集中管理。
  • 状态管理器或控制器层,用于管理不同视图组件的状态更新和事件分发。

4.优缺点及适用环境

优点:

  • 减少依赖:减少了同事对象之间的直接依赖,降低了系统的耦合度。
  • 简化交互:通过中介者集中管理对象间的交互,使得代码更加清晰易读。
  • 易于扩展:新增同事对象时不需要修改现有的同事对象,只需调整中介者即可。

缺点:

  • 复杂性增加:如果中介者变得过于复杂,可能会成为系统的瓶颈,同时也会增加维护成本。
  • 单一职责原则:如果中介者承担过多的责任,可能会导致其变得庞大且难以管理。

应用环境:

  • 当系统中有大量对象需要相互通信,但你希望避免它们之间的直接引用时。
  • 对于那些希望通过引入中介者来提高模块独立性的系统来说,中介者模式是一个很好的选择。
  • 在开发复杂的GUI应用程序时,使用中介者模式可以帮助更好地管理和控制组件之间的交互。

      通过职责链模式,我们可以构建更加灵活、易于扩展的应用程序,尤其是在涉及多种类型的请求处理时。然而,在使用此模式时也应注意其可能带来的性能损耗和复杂性的增加。

5.举一反三

中介者模式因其能有效减少对象间的直接依赖和简化复杂的交互逻辑,适用于多种场景。以下是一些可以应用中介者模式的具体例子及其应用场景:

1. GUI应用程序

在Qt或其他GUI框架中,组件(如按钮、文本框等)之间的交互往往比较复杂。使用中介者模式可以帮助管理这些交互,避免组件间直接相互引用。

  • 示例:在一个表单中,某些输入框的可用性可能取决于其他输入框的内容或状态。例如,选择“是否需要发票”复选框后,相关的税号输入框才变为可编辑状态。通过引入一个中介者来监听这些事件并更新相应的UI组件状态,可以使代码更加清晰且易于维护。

2. 分布式系统中的模块通信

在分布式系统或微服务架构中,各个服务或模块之间需要进行通信。为了避免服务之间的直接依赖,可以通过引入中介者(如消息队列或API网关)来解耦这些服务。

  • 示例:在一个电商系统中,订单服务、库存服务和支付服务都需要相互通信以完成下单流程。使用中介者模式可以确保这些服务不直接相互调用,而是通过中介者传递消息,从而提高了系统的灵活性和可扩展性。

3. 游戏开发中的物体交互

在游戏中,不同游戏物体(如角色、敌人、道具等)之间的交互非常频繁。使用中介者模式可以帮助管理这些交互,特别是当涉及到多个物体同时对同一事件作出反应时。

  • 示例:在一个多人在线游戏中,当玩家捡起一件装备时,不仅该玩家的状态会发生变化,其他玩家也可能看到这一变化。通过引入一个中介者来协调这些状态更新,可以有效地管理复杂的同步逻辑。

4. 状态管理和事件分发

在具有复杂状态的应用程序中,比如企业级应用或大型网站,状态的变化可能会影响到多个视图或组件。使用中介者模式可以帮助集中管理这些状态变化,并通知相关联的视图或组件进行更新。

  • 示例:在一个具有多个视图的单页应用(SPA)中,用户登录状态的变化可能会影响导航栏、侧边栏等多个地方。通过使用中介者来处理这种状态变化,并向所有相关视图广播通知,可以使状态管理更加简洁高效。

5. 智能家居控制系统

智能家居设备(如灯光、温度控制器、安全系统等)通常需要根据环境变化或其他设备的状态自动调整其行为。使用中介者模式可以使得这些设备之间的交互更加灵活和独立。

  • 示例:当智能门锁检测到有人进入房屋时,它可以通过中介者通知室内照明系统开启特定区域的灯光,并告知温控器调整室温。这种方式既实现了设备间的解耦,又保证了响应的及时性和准确性。

总之,中介者模式非常适合用于那些需要管理多个对象间复杂交互的场景,特别是在希望减少对象间直接依赖、提高模块独立性以及简化交互逻辑的情况下。通过合理地应用中介者模式,可以构建出更加灵活、易于维护和扩展的软件系统。

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

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

相关文章

golang常用库之-swaggo/swag根据注释生成接口文档

golang常用库之-swaggo/swag库根据注释生成接口文档 什么是swaggo/swag github&#xff1a;https://github.com/swaggo/swag 参考文档&#xff1a;https://golang.halfiisland.com/community/pkgs/web/swag.html#%E4%BD%BF%E7%94%A8 swaggo/swag 是 Swagger API 2.0 在 go 语…

爬取网站内容转为markdown 和 html(通常模式)

我们遇到一些自己喜欢内容&#xff0c;想保存下来&#xff0c;手动复制粘贴很麻烦&#xff0c;我们使用 python 来爬取这些内容。 一、代码 downlod.py import os import requests from bs4 import BeautifulSoup from urllib.parse import urljoin# 目标网页&#xff08;可…

. Spring MVC

&#xff08;1&#xff09;MVC 设计模式 Model&#xff08;模型&#xff09;&#xff1a;负责存储数据和业务逻辑。在 Spring MVC 中&#xff0c;模型通常是 JavaBean&#xff0c;用于封装数据。 View&#xff08;视图&#xff09;&#xff1a;负责展示数据给用户。可以是 JSP…

高效执行自动化用例:分布式执行工具pytest-xdist实战!

01、声明 在介绍pytest-xdist时&#xff0c;不讲任何原理&#xff0c;需要看原理的请移至官方&#xff1a;https://pypi.org/project/pytest-xdist/ 当我们自动化测试用例非常多的时候&#xff0c; 一条条按顺序执行会非常慢&#xff0c;pytest-xdist的出现就是为了让自动化测…

【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第十八节】

ISO 14229-1:2023 UDS诊断服务测试用例全解析&#xff08;ResponseOnEvent_0x86服务&#xff09; 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月14日 关键词&#xff1a;UDS协议、0x86服务、事件响应、ISO 14229-1:2023、ECU测试 一、服务功能概述 0x86…

deepseek多列数据对比,联想到excel的高级筛选功能

目录 1 业务背景 ​2 deepseek提示词输入 ​3 联想分析 4 EXCEL高级搜索 1 业务背景 系统上线的时候经常会遇到一个问题&#xff0c;系统导入的数据和线下的EXCEL数据是否一致&#xff0c;如果不一致&#xff0c;如何快速找到差异值&#xff0c;原来脑海第一反应就是使用公…

TailwindCss的vue3安装使用

按照官网的安装教程&#xff0c;属性最后无法生效&#xff0c;这是自我改良版&#xff0c;添加了额外步骤&#xff0c;但是每次引入新的tailwindcss属性 需要重新跑一次项目 npm下载tailwindcss npm install -D tailwindcss npx初始化tailwind配置 npx tailwindcss init 此时根…

个人博客测试报告

一、项目背景 个人博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来存储相关的数据&#xff0c;同时将其部署到云服务器上。前端主要有四个页面构成&#xff1a;登录页、列表页、详情页以及编辑页&#xff0c;以上模拟实现了最简单的个人博客系统。其结合后…

Python----数据结构(单链表:节点,是否为空,长度,遍历,添加,删除,查找)

一、链表 链表是一种线性数据结构&#xff0c;由一系列按特定顺序排列的节点组成&#xff0c;这些节点通过指针相互连接。每个节点包含两部分&#xff1a;元素和指向下一个节点的指针。其中&#xff0c;最简单的形式是单向链表&#xff0c;每个节点含有一个信息域和一个指针域&…

夜莺监控发布 v8.beta5 版本,优化 UI,新增接口认证方式便于鉴权

以防读者不了解夜莺&#xff0c;开头先做个介绍&#xff1a; 夜莺监控&#xff0c;英文名字 Nightingale&#xff0c;是一款侧重告警的监控类开源项目。类似 Grafana 的数据源集成方式&#xff0c;夜莺也是对接多种既有的数据源&#xff0c;不过 Grafana 侧重在可视化&#xff…

什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用

什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用 目录 什么是Embedding、RAG、Function calling、Prompt engineering、Langchain、向量数据库? 怎么使用Embedding(嵌入)RAG(检索增强生成)Function calling(函数调用)Pr…

SQLMesh 系列教程5- 详解SQL模型

本文将详细介绍 SQLMesh 的 SQL 模型组成要素及其在实际项目中的应用。SQLMesh 是一个强大的数据工程工具&#xff0c;其 SQL 模型由 MODEL DDL、预处理语句、主查询、后处理语句以及可选的 ON VIRTUAL UPDATE 语句组成。我们将通过一个电商平台每日销售报告的实例&#xff0c;…

DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入)

前言 在当今数字化时代&#xff0c;AI编程助手已成为提升开发效率的利器。DeepSeek作为一款强大的AI模型&#xff0c;凭借其出色的性能和开源免费的优势&#xff0c;成为许多开发者的首选。今天&#xff0c;就让我们一起探索如何将DeepSeek接入PyCharm&#xff0c;实现高效、智…

从驾驶员到智能驾驶:汽车智能化进程中的控制与仿真技术

在汽车技术持续演进的历程中&#xff0c;人类驾驶员始终是一个极具研究价值的智能控制系统“原型”。驾驶员通过视觉感知、行为决策与操作执行的闭环控制&#xff0c;将复杂的驾驶任务转化为车辆的实际动作&#xff0c;同时动态适应道路环境的变化。这一过程不仅体现了高度的自…

Spring Boot项目的基本设计步骤和相关要点介绍

以下是一个关于Spring Boot项目的基本设计步骤和相关要点介绍,我们以一个简单的示例应用——员工管理系统为例进行说明: 一、项目概述 员工管理系统旨在实现对公司员工信息的有效管理,包括员工基本信息录入、查询、更新以及删除等功能。通过Spring Boot框架来快速搭建后端…

【Java】泛型与集合篇(一)

泛型与集合(一) 泛型泛型的核心作用泛型类型(类)定义与使用类型参数命名约定泛型方法定义与调用与泛型类的区别通配符上界通配符下界通配符有界类型参数类型擦除集合框架核心接口Collection 接口Map 接口Collection 接口操作的常用方法基本操作批量操作数组操作流操作方法L…

HarmonyOS组件之Tabs

Tabs 1.1概念 Tabs 视图切换容器&#xff0c;通过相适应的页签进行视图页面的切换的容器组件每一个页签对应一个内容视图Tabs拥有一种唯一的子集元素TabContent 1.2子组件 不支持自定义组件为子组件&#xff0c;仅可包含子组件TabContent&#xff0c;以及渲染控制类型 if/e…

华为FusionCompute虚拟化平台

一、华为FusionCompute虚拟化套件介绍 华为FusionCompute虚拟化套件是业界领先的虚拟化解决方案&#xff0c;能够帮助客户带来如下的价值&#xff0c;从而大幅提升数据中心基础设施的效率。 帮助客户提升数据中心基础设施的资源利用率&#xff1b;帮助客户成倍缩短业务上线周期…

使用apt-rdepends制作软件离线deb安装包

使用apt-rdepends制作软件离线deb安装包 除基础软件外&#xff0c;还要获取软件依赖包。 依赖包工具安装 apt-get install apt-rdependsapt-rdepends工具使用 使用apt-rdepends工具&#xff0c;递归方式分析软件依赖&#xff0c;下载软件包本体&#xff0c;和依赖包。制作时…

【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑩】

ISO 14229-1:2023 UDS诊断【ECU复位0x11服务】_TestCase10 作者&#xff1a;车端域控测试工程师 更新日期&#xff1a;2025年02月18日 关键词&#xff1a;UDS诊断协议、ECU复位服务、0x11服务、ISO 14229-1:2023 TC11-010测试用例 用例ID测试场景验证要点参考条款预期结果TC…