设计模式(行为型)-中介者模式

article/2025/6/29 9:57:28

目录

定义

类图结构展示

角色职责详解

模式的优缺点分析

优点

缺点

适用场景

应用实例

与其他模式的结合与拓展

总结


定义

        中介者模式的核心思想可以概括为:用一个中介对象来封装一系列的对象交互。这个中介者就像一个通信枢纽,使各对象不需要显式地相互引用,从而降低它们之间的耦合度,并且可以独立地改变它们之间的交互规则。这种模式的本质是将对象之间的多对多交互转化为对象与中介者之间的一对多交互,通过中介者的协调来维持系统的正常运转。

类图结构展示

角色职责详解

  • 抽象中介者(Mediator)角色:它是中介者的接口,定义了同事对象注册与转发同事对象信息的抽象方法。这个角色为具体中介者提供了统一的接口规范,确保所有中介者实现都具备基本的通信协调能力。

  • 具体中介者(ConcreteMediator)角色:实现中介者接口,通常会维护一个用于管理同事对象的列表。它的核心职责是协调各个同事角色之间的交互关系,因此必然依赖于同事角色。具体中介者是交互逻辑的实际承载者,它根据不同的业务场景实现具体的协调逻辑。

  • 抽象同事(Colleague)角色:定义同事类的接口,保存中介者对象的引用,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。通过持有中介者的引用,同事对象可以将交互请求委托给中介者处理。

  • 具体同事类(Concrete Colleague)角色:是抽象同事类的具体实现者。当需要与其他同事对象交互时,不再直接调用其他同事的方法,而是将请求发送给中介者对象,由中介者负责后续的交互协调。这种方式彻底解耦了同事之间的直接依赖。

模式的优缺点分析

优点

  • 简化对象关系,实现松耦合:中介者模式将系统中各个对象之间的复杂相互关系进行封装,把原本多对多的混乱交互转化为对象与中介者之间的一对多交互。这种封装使得各个同事类之间解耦,系统变为松耦合的结构,大大降低了系统的理解和维护难度。当某个同事类发生变化时,只要其与中介者的接口不变,就不会对其他同事类产生直接影响。

  • 提高系统灵活性,便于复用:由于同事对象与中介者之间是松耦合的,各个同事对象可以独立地进行开发和测试,并且易于复用。当需要在不同的场景中使用相同的同事类时,只需搭配不同的中介者实现即可,而无需修改同事类的代码。这种灵活性使得系统能够更好地应对需求的变化和扩展。

缺点

  • 中介者责任过重:在中介者模式中,中介者角色承担了过多的责任,它几乎掌握了所有同事对象的交互逻辑。这就导致一旦中介者对象出现问题,整个系统的交互机制将会受到重大影响,甚至可能导致系统崩溃。因此,在设计中介者时,需要谨慎考虑其复杂性,避免使其成为系统的单一故障点。

  • 扩展新同事类的局限性:当需要新增加一个同事类时,往往不得不去修改抽象中介者类和具体中介者类,以处理新同事类与其他同事类之间的交互逻辑。这种修改可能会违背 “开闭原则”,增加系统的维护成本。为了解决这个问题,可以考虑结合观察者模式和状态模式来灵活扩展中介者的功能,减少对原有代码的修改。

适用场景

  • 对象间存在复杂交互的系统:当一组定义良好的对象需要进行复杂的相互通信,且这些对象之间的交互关系呈现出网状结构时,中介者模式是一个很好的选择。例如,在图形界面设计中,窗口中的各种控件(按钮、文本框、列表框等)之间可能存在复杂的交互关系,使用中介者模式可以将这些交互逻辑集中到中介者中,使控件之间解耦。

  • 希望通过中间类封装多类行为的场景:当你想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类时,中介者模式非常适用。它通过中介者统一管理各对象的交互,避免了因对象间直接交互而导致的类爆炸问题。

应用实例

        以一个简单的聊天系统为例,多个用户(同事类)通过聊天服务器(中介者)进行消息交流:

from abc import ABC, abstractmethodfrom typing import List# 抽象中介者:聊天服务器class ChatMediator(ABC):@abstractmethoddef register_user(self, user):pass@abstractmethoddef send_message(self, message, sender):pass# 具体中介者:实现聊天服务器功能class ConcreteChatMediator(ChatMediator):def __init__(self):self.users: List[User] = []def register_user(self, user):if user not in self.users:self.users.append(user)user.set_mediator(self)def send_message(self, message, sender):for user in self.users:# 不向发送者自己发送消息if user != sender:user.receive_message(message)# 抽象同事:用户class User(ABC):def __init__(self, name):self.name = nameself.mediator = Nonedef set_mediator(self, mediator):self.mediator = mediator@abstractmethoddef send_message(self, message):pass@abstractmethoddef receive_message(self, message):pass# 具体同事:实现用户功能class ConcreteUser(User):def send_message(self, message):print(f"{self.name} 发送消息: {message}")if self.mediator:self.mediator.send_message(message, self)def receive_message(self, message):print(f"{self.name} 接收消息: {message}")# 使用示例if __name__ == "__main__":# 创建中介者mediator = ConcreteChatMediator()# 创建同事对象user1 = ConcreteUser("张三")user2 = ConcreteUser("李四")user3 = ConcreteUser("王五")# 注册同事到中介者mediator.register_user(user1)mediator.register_user(user2)mediator.register_user(user3)# 同事之间通过中介者交互user1.send_message("大家好,这是一个中介者模式的示例!")user2.send_message("你好,张三,很高兴学习这个模式!")user3.send_message("我也来参与讨论,中介者模式确实很有用!")

        在这个示例中,聊天服务器(ConcreteChatMediator)作为中介者,管理着所有用户(ConcreteUser)的注册,并负责转发消息。用户之间无需直接知道彼此的存在,只需通过中介者进行通信,实现了对象之间的解耦。

与其他模式的结合与拓展

        当面临新增加同事类需要修改中介者的问题时,可以结合观察者模式来优化。将中介者作为观察者,同事类作为被观察者,当同事类状态发生变化时,通知中介者进行相应的处理,从而减少对中介者代码的直接修改。此外,状态模式也可以与中介者模式结合使用,根据不同的状态让中介者采用不同的交互策略,使系统更加灵活和可扩展。

总结

        中介者模式通过引入中介者对象,巧妙地化解了对象间复杂的交互难题,为构建松耦合、可维护的软件系统提供了有力的支持。在实际开发中,合理运用该模式可以使系统架构更加清晰,代码更加简洁,从而提高软件开发的效率和质量。


http://www.hkcw.cn/article/BNhNAHPkUg.shtml

相关文章

PMOS以及电源转换电路设计

PMOS的使用 5V_EN5V时&#xff0c;PMOS截止&#xff1b; 5V_EN0V时&#xff0c;PMOS导通&#xff1b; 电源转换电路 当Vout0V时&#xff0c;Vg0V, Vgs>Vth, PMOS导通&#xff0c;只有电池供电&#xff1b; 当Vout5V时&#xff0c;Vg4.9V, Vs4.8V?, Vgs<Vth, PMOS截止&am…

本地部署 DeepSeek R1(最新)【从下载、安装、使用和调用一条龙服务】

文章目录 一、安装 Ollama1.1 下载1.2 安装 二、下载 DeepSeek 模型三、使用 DeepSeek3.1 在命令行环境中使用3.2 在第三方软件中使用 一、安装 Ollama 1.1 下载 官方网址&#xff1a;Ollama 官网下载很慢&#xff0c;甚至出现了下载完显示 无法下载&#xff0c;需要授权 目…

数据治理的演变与AI趋势

知识星球&#xff1a;数据书局。打算通过知识星球将这些年积累的知识分享出来&#xff0c;让各位在数据治理、数据分析的路上少走弯路&#xff0c;另外星球也方便动态更新最近的资料&#xff0c;提供各位一起讨论数据的小圈子 1.数据治理的演变 1.1.摘要 数据治理是指组织管…

Fullstack 面试复习笔记:操作系统 / 网络 / HTTP / 设计模式梳理

Fullstack 面试复习笔记&#xff1a;操作系统 / 网络 / HTTP / 设计模式梳理 面试周期就是要根据JD调整准备内容&#xff08;挠头&#xff09;&#xff0c;最近会混合复习针对全栈这块的内容&#xff0c;目前是根据受伤的JD&#xff0c;优先选择一些基础的操作系统、Java、Nod…

【MIMO稳定裕度】基于数据驱动的多输入多输出系统稳定裕度分析

最近一直在忙着写论文&#xff0c;只能说要写一篇高水平论文确实不容易&#xff0c;要一直反复来回修改调整&#xff0c;要求比较高&#xff0c;所以没太有时间和精力写博客&#xff0c;这两天结束了初稿&#xff0c;又正好是假期&#xff0c;出来冒个泡。 本次分享的主题是&am…

Python 训练营打卡 Day 33-神经网络

简单神经网络的流程 1.数据预处理&#xff08;归一化、转换成张量&#xff09; 2.模型的定义 继承nn.Module类 定义每一个层 定义前向传播流程 3.定义损失函数和优化器 4.定义训练过程 5.可视化loss过程 预处理补充&#xff1a; 分类任务中&#xff0c;若标签是整…

TDengine 的 AI 应用实战——电力需求预测

作者&#xff1a; derekchen Demo数据集准备 我们使用公开的UTSD数据集里面的电力需求数据&#xff0c;作为预测算法的数据来源&#xff0c;基于历史数据预测未来若干小时的电力需求。数据集的采集频次为30分钟&#xff0c;单位与时间戳未提供。为了方便演示&#xff0c;按…

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡 一、项目背景与转型原因 1.1 原定计划的变更 本系列教程最初规划是开发即构美颜SDK的UTS插件&#xff0c;但由于甲方公司内部战略调整&#xff0c;原项目被迫中止。考虑到&#xff1a; 技术…

(aaai2024) Omni-Kernel Network for Image Restoration

代码&#xff1a;https://github.com/c-yn/OKNet 研究动机&#xff1a;作者认为Transformer模型计算复杂度太高&#xff0c;因此提出了 omni-kernel module &#xff08;OKM&#xff09;&#xff0c;可以有效的学习局部到全局的特征表示。该模块包括&#xff1a;全局、大分支、…

useMemo useCallback 自定义hook

useMemo & useCallback & 自定义hook useMemo 仅当依赖项发生变化的时候&#xff0c;才去重新计算&#xff1b;其他状态变化时则不去做不必要的计算。 useCallback 缓存函数。但是使用注意&#x1f4e2; &#xff0c;useCallback没有特别明显的优化。 *合适的场景——父…

android binder(二)应用层编程实例

一、binder驱动浅析 从上图看出&#xff0c;binder的通讯主要涉及三个步骤。 在 Binder Server 端定义好服务&#xff0c;然后向 ServiceManager 注册服务在 Binder Client 中向 ServiceManager 获取到服务发起远程调用&#xff0c;调用 Binder Server 中定义好的服务 整个流…

GESP2024年3月认证C++二级( 第三部分编程题(2)小杨的日字矩阵)

参考程序&#xff1a; #include <iostream> using namespace std;int main() {int n;cin >> n; // 读入奇数 n// 外层循环控制每一行for (int i 0; i < n; i) {// 内层循环控制每一列for (int j 0; j < n; j) {char ch;// 如果当前列是最左或最右&#x…

BUUCTF[ACTF2020 新生赛]Exec 1题解

BUUCTF[ACTF2020 新生赛]Exec 1题解 分析解题过程总结: 分析 先分析题目&#xff1a;exc()是一个内部调用shell命令的函数&#xff0c;同样的函数还有system(), 创建靶机&#xff0c;打开网址&#xff0c;是一个和PING相关的网页&#xff0c;查看源代码&#xff0c;没有提示&a…

NX869NX874美光固态颗粒NX877NX883

NX869NX874美光固态颗粒NX877NX883 美光固态硬盘颗粒技术解析与市场展望 近年来&#xff0c;固态硬盘&#xff08;SSD&#xff09;市场呈现出蓬勃发展的态势&#xff0c;而作为核心组件的存储颗粒&#xff0c;其技术进展与市场动态自然吸引了众多关注。在众多品牌中&#xff…

CodeTop100 Day20

58、翻转字符串中的数字 class Solution {public String reverseWords(String s) {s s.trim(); int j s.length() - 1, i j;StringBuilder res new StringBuilder();while (i > 0) {while (i > 0 && s.charAt(i) ! ) i--…

重温经典算法——快速排序

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 基本原理 快速排序基于分治思想&#xff0c;通过选取基准元素将数组划分为两个子数组&#xff08;小于基准和大于基准&#xff09;&#xff0c;递归排序子数组。平均时间复…

【机器学习】集成学习与梯度提升决策树

目录 一、引言 二、自举聚合与随机森林 三、集成学习器 四、提升算法 五、Python代码实现集成学习与梯度提升决策树的实验 六、总结 一、引言 在机器学习的广阔领域中,集成学习(Ensemble Learning)犹如一座闪耀的明星,它通过组合多个基本学习器的力量,创造出…

Python量化交易:K线形态识别与技术分析可视化

引言 在量化交易领域&#xff0c;K线形态识别是一种重要的技术分析方法&#xff0c;可以帮助投资者预测市场趋势并制定交易策略。本文将介绍如何使用Python实现K线形态的自动识别与可视化分析&#xff0c;无需依赖复杂的第三方库如TA-Lib&#xff0c;完全使用纯Python实现。通…

前端自动化测试利器:Playwright 全面介绍

目录 &#x1f9ea; 前端自动化测试利器&#xff1a;Playwright 全面介绍 ✨ 为什么选择 Playwright&#xff1f; 1. 跨浏览器支持 2. 多语言支持 3. 自动等待机制 4. 强大的页面交互能力 &#x1f527; Playwright 快速上手 &#x1f4f8; 更强的调试体验 &#x1f9…

华为云Flexus+DeepSeek征文|华为云 Dify 打造智慧水果分析助手,实现“知识库 + 大模型”精准赋能

前言 本文聚焦基于华为云平台部署的智慧水果分析助手 AI Agent&#xff0c;通过 Dify 平台集成 Embedding、Rerank 及 DeepSeek 模型&#xff0c;构建工作流&#xff0c;实现提问内容驱动的 “知识库 大模型” 与 “联网搜索 大模型” 智能切换。 ECS控制台&#xff1a;https…