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

news2025/6/5 3:13:55

目录

定义

类图结构展示

角色职责详解

模式的优缺点分析

优点

缺点

适用场景

应用实例

与其他模式的结合与拓展

总结


定义

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

类图结构展示

角色职责详解

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

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

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

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

模式的优缺点分析

优点

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

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

缺点

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

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

适用场景

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

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

应用实例

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

from abc import ABC, abstractmethod

from typing import List

# 抽象中介者:聊天服务器

class ChatMediator(ABC):

@abstractmethod

def register_user(self, user):

pass

@abstractmethod

def 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 = name

self.mediator = None

def set_mediator(self, mediator):

self.mediator = mediator

@abstractmethod

def send_message(self, message):

pass

@abstractmethod

def 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.coloradmin.cn/o/2396678.html

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

相关文章

【Java学习笔记】异常

异常(Exception) 一、基本介绍 在 Java 程序中,将运行中发生的不正常情况称为 “异常”,开发过程中的语法错误和运行时发生的异常情况是不一样的。 二、异常的分类 1. Error(错误):Java 虚拟…

MySQL:视图+用户管理+访问+连接池原理

一、视图 视图是一个虚拟表,其内容由查询定义。同真实的表一样(相当于是把查询的内容当成一个临时表来使用),视图包含一系列带有名称的列和行数据。视图的数据变化会影响到基表,基表的数据变化也会影响到视图。 1.1 为…

neo4j 5.19.0安装、apoc csv导入导出 及相关问题处理

前言 突然有需求需要用apoc 导入 低版本的图谱数据,网上资料又比较少,所以就看官网资料并处理了apoc 导入的一些问题。 相关地址 apoc 官方安装网址 apoc 官方导出csv 教程地址 apoc 官方 导入 csv 地址 docker 安装 执行如下命令启动镜像 doc…

无人机桥梁3D建模的拍摄频率

无人机桥梁3D建模的拍摄频率 无人机桥梁3D建模的拍摄频率(每秒拍摄照片数)需根据建模精度、飞行速度、相机性能等因素综合确定。以下是专业级作业的详细参数分析: 1. 核心计算公式 拍摄频率(fps) \frac{飞行速度&…

ESP32-idf学习(三)esp32C3连接iot

一、前言 上一篇用蓝牙作为通信方式,虽然勉强完成了控制,但结果显然不是那么符合我们的预期,既然用蓝牙还需要研究一段时间,那我们就先整一些现成的,不需要研究的!iot云平台!这里当然也是通过w…

详解鸿蒙仓颉开发语言中的计时器

今天又到了大家喜闻乐见的科普环节,也可以说是踩坑环节,哈哈哈。今天聊一聊仓颉开发语言中的计时器,这部分可老有意思了。 为什么这么说呢,因为关于仓颉的计时器你几乎搜不到任何的文档,也没有相关的代码提示&#xf…

【计算机网络】第3章:传输层—拥塞控制原理

目录 一、PPT 二、总结 (一)拥塞的定义 (二)拥塞产生的原因 (三)拥塞控制的目标 (四)拥塞控制方法分类 1. 端到端拥塞控制 2. 网络辅助拥塞控制 (五)…

Vue3(watch,watchEffect,标签中ref的使用,TS,props,生命周期)

Vue3(watch,watchEffect,标签中ref的使用,TS,props,生命周期) watch监视 情况三:监视reactive定义的对象类型的数据 监视reactive定义的对象类型的数据,默认开启深度监视。地址没变,新值和旧…

【nssctf第三题】[NSSCTF 2022 Spring Recruit]easy C

这是题目&#xff0c;下载附件打开是个C文件 #include <stdio.h> #include <string.h>int main(){char a[]"wwwwwww";char b[]"dvxbQd";//try to find out the flagprintf("please input flag:");scanf(" %s",&a);if…

DBeaver导入/导出数据库时报错解决方案

导出&#xff1a; 报错&#xff1a;mysqldump: Got error: 2026: SSL connection error: error:0A000102:SSL routines::unsupported protocol when trying to connect 在额外的命令参数中添加"--ssl-modeDISABLED"可以关闭SSL服务&#xff0c;从而成功解决问题。这…

uniapp与微信小程序开发平台联调无法打开IDE

经测试属于网络问题。本机需要联网。否则会出现Hbuilder运行微信小程序到模拟器时无法打开 微信开发者工具 这个页面出不来会一直显示异常。这期间微信小程序开发工具的端口是通的 需要先联网

第十二节:第五部分:集合框架:Set集合的特点、底层原理、哈希表、去重复原理

Set系列集合特点 哈希值 HashSet集合的底层原理 HashSet集合去重复 代码 代码一&#xff1a;整体了解一下Set系列集合的特点 package com.itheima.day20_Collection_set;import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.…

【C++项目】:仿 muduo 库 One-Thread-One-Loop 式并发服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;C从入门到精通 目录 &#x1f525; 前言 一&#xff1a;&#x1f525; 项目储备知识 &#x1f98b; HTTP 服务器&#x1f98b; Reactor 模型&#x1f380; 单 Reactor 单线程&#xff1a;单I/O多路…

基于大数据的个性化购房推荐系统设计与实现(源码+定制+开发)面向房产电商的智能购房推荐与数据可视化系统 基于Spark与Hive的房源数据挖掘与推荐系统设计

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

FFmpeg学习笔记

1. 播放器的架构 2. 播放器的渲染流程 3. ffmpeg下载与安装 3.0 查看PC是否已经安装了ffmpeg ffmpeg 3.1 下载 wget https://ffmpeg.org/releases/ffmpeg-7.0.tar.gz 3.2 解压 tar zxvf ffmpeg-7.0.tar.gz && cd ./ffmpeg-7.0 3.3 查看配置文件 ./configure …

Chrome 通过FTP,HTTP 调用 Everything 浏览和搜索本地文件系统

【提问1】 Chrome调用本地 everything.exe, everything 好像有本地 FTP 服务器&#xff1f; 【DeepSeek R1 回答】 是的&#xff0c;Everything 确实内置了 HTTP/FTP 服务器功能&#xff0c;这提供了一种相对安全的浏览器与本地应用交互的方式。以下是完整的实现方案&#x…

GpuGeek如何成为AI基础设施市场的中坚力量

AI时代&#xff0c;算力基础设施已成为支撑技术创新和产业升级的关键要素。作为国内专注服务算法工程师群体的智算平台&#xff0c;GpuGeek通过持续创新的服务模式、精准的市场定位和系统化的生态建设&#xff0c;正快速成长为AI基础设施领域的中坚力量。本文将深入分析GpuGeek…

【Hot 100】45. 跳跃游戏 II

目录 引言跳跃游戏 IIdp解题贪心解题 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题&#xff1a;【Hot 100】45. 跳跃游戏 II❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难&#xff01; 引言 跳跃…

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术

Python数学可视化——显函数、隐函数及复杂曲线的交互式绘图技术 一、引言 在科学计算和数据分析中&#xff0c;函数与方程的可视化是理解数学关系和物理现象的重要工具。本文基于Python的Tkinter和Matplotlib库&#xff0c;实现一个功能完善的函数与方程可视化工具&#xff…

代码随想录打卡|Day51 图论(dijkstra(堆优化版)精讲、Bellman_ford 算法精讲)

图论part09 dijkstra&#xff08;堆优化版&#xff09;精讲(不熟悉) 代码随想录链接 题目链接 import java.util.*;class Edge {int to; // 邻接顶点int val; // 边的权重Edge(int to, int val) {this.to to;this.val val;} }class MyComparison implements Comparator<…