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

设计模式 20 中介者模式 Mediator Pattern

设计模式 20 中介者模式 Mediator Pattern
1.定义

中介者模式(Mediator Pattern)是一种行为型设计模式,它通过封装对象之间的交互,促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象,将系统中对象之间复杂的交互关系集中管理,使得对象之间不直接相互通信,而是通过中介者进行通信,从而降低对象之间的耦合度,提高系统的可维护性和扩展性。

在中介者模式中,中介者对象充当了协调者的角色,负责处理系统中各个相互关联对象之间的交互,对于系统其他对象来说,与中介者进行通信是唯一的接口。此外,中介者模式还可以实现集中化控制,将系统变得更加灵活,并且可以更方便地修改系统的行为。


2.内涵


中介者模式(Mediator Pattern)主要角色:

  1. 中介者(Mediator):定义一个接口用于与各同事对象之间的通信,可以是抽象类或接口,并且通常包含一个或多个方法用于处理不同对象之间的交互。
  2. 具体中介者(Concrete Mediator):实现中介者接口,负责协调各个同事对象的交互关系。
  3. 同事(Colleague):每个同事对象都有一个中介者对象的引用,通过中介者来与其他同事对象进行通信。
  4. 具体同事(Concrete Colleague):实现同事接口的类,与其他同事对象进行交互,通过中介者来处理与其他同事对象的通信。

中介者模式通常适用的场景:

系统中的对象之间具有复杂的交互关系,需要通过中介者来协调。
系统需要支持松耦合的设计,希望减少对象之间的直接依赖。
多个对象之间存在循环依赖,通过引入中介者来解决循环依赖问题。

上述角色之间的关系,简而言之,绘制如下UML 。


     
3.使用示例
#include <iostream>
#include <string>/*** The Mediator interface declares a method used by components to notify the* mediator about various events. The Mediator may react to these events and* pass the execution to other components.*/
class BaseComponent;class Mediator {public:virtual void Notify(BaseComponent *sender, std::string event) const = 0;
};/*** The Base Component provides the basic functionality of storing a mediator's* instance inside component objects.*/
class BaseComponent {protected:Mediator *mediator_;public:BaseComponent(Mediator *mediator = nullptr) : mediator_(mediator) {}void set_mediator(Mediator *mediator) {this->mediator_ = mediator;}
};/*** Concrete Components implement various functionality. They don't depend on* other components. They also don't depend on any concrete mediator classes.*/
class Component1 : public BaseComponent {public:void DoA() {std::cout << "Component 1 does A.\n";this->mediator_->Notify(this, "A");}void DoB() {std::cout << "Component 1 does B.\n";this->mediator_->Notify(this, "B");}
};class Component2 : public BaseComponent {public:void DoC() {std::cout << "Component 2 does C.\n";this->mediator_->Notify(this, "C");}void DoD() {std::cout << "Component 2 does D.\n";this->mediator_->Notify(this, "D");}
};/*** Concrete Mediators implement cooperative behavior by coordinating several* components.*/
class ConcreteMediator : public Mediator {private:Component1 *component1_;Component2 *component2_;public:ConcreteMediator(Component1 *c1, Component2 *c2) : component1_(c1), component2_(c2) {this->component1_->set_mediator(this);this->component2_->set_mediator(this);}void Notify(BaseComponent *sender, std::string event) const override {if (event == "A") {std::cout << "Mediator reacts on A and triggers following operations:\n";this->component2_->DoC();}if (event == "D") {std::cout << "Mediator reacts on D and triggers following operations:\n";this->component1_->DoB();this->component2_->DoC();}}
};/*** The client code.*/void ClientCode() {Component1 *c1 = new Component1;Component2 *c2 = new Component2;ConcreteMediator *mediator = new ConcreteMediator(c1, c2);std::cout << "Client triggers operation A.\n";c1->DoA();std::cout << "\n";std::cout << "Client triggers operation D.\n";c2->DoD();delete c1;delete c2;delete mediator;
}int main() {ClientCode();return 0;
}

类图如下所示 


4.注意事项


在使用中介者模式(Mediator Pattern)时,需要注意以下几个点和可能遇到的坑:

  • 考虑中介者对象的复杂性:中介者对象负责管理对象之间的交互关系,可能会变得复杂,特别是在系统中有大量对象需要协作时。因此,在设计中介者对象时,需要仔细考虑其职责和功能,避免过于臃肿和复杂。
  • 避免中介者成为系统瓶颈:由于所有对象之间的通信通过中介者进行,中介者可能会成为系统的性能瓶颈。因此,在使用中介者模式时,需要考虑中介者的设计和实现是否能够满足系统的性能需求。
  • 避免过度集中化控制:中介者模式的目的是降低对象之间的耦合度并集中控制交互逻辑,但过度集中化控制可能导致系统设计变得僵化和不灵活。因此,在设计中介者模式时,需要根据实际需求来平衡对象之间的关系和控制逻辑。
  • 同事对象之间的交互:中介者模式可以减少对象之间的直接依赖,但所有对象间的交互都需要通过中介者进行,可能会导致系统的复杂性增加。因此,需要合理划分对象的职责和功能,避免同事对象之间过于紧密的交互。
  • 考虑扩展性和灵活性:中介者模式可以使系统更加灵活和可扩展,但在设计中介者对象时,需要考虑系统的未来发展和变化。确保中介者模式能够支持系统的扩展和变化,避免设计过于局限于当前需求。
5.最佳实践

在设计中介者模式(Mediator Pattern)时,以确保模式的有效实现和系统的可维护性。以下一些可以参考的设计实践:

  • 使用抽象中介者(Mediator)接口:定义一个抽象中介者接口,定义同事对象与中介者之间的通信方法,以实现解耦和系统扩展。
  • 采用单一职责原则:确保中介者对象的职责单一,不要让中介者对象负责过多的功能和逻辑,以提高系统的灵活性和可维护性。
  • 考虑中介者对象的实现方式:中介者对象可以采用抽象类或接口的形式实现,也可以选择使用具体类实现。根据实际需求和系统复杂度选择适合的实现方式。
  • 考虑同事对象的接口设计:同事对象之间通过中介者进行通信,因此需要定义好同事对象的接口,确保适当的信息传递和约束。
  • 考虑系统的扩展性:在设计中介者模式时,要考虑系统未来的扩展和变化,确保模式能够支持新的同事对象和中介者对象的加入,以确保系统的可扩展性。
  • 想清楚对象之间的通信流程:在设计中介者模式时,要精确定义对象之间的通信流程和交互规则,避免对象间的混乱和冲突。
  • 使用工厂模式创建中介者和同事对象:可以使用工厂模式来创建中介者对象和同事对象,以确保对象的创建过程更加灵活和可控。
  • 使用观察者模式实现通知机制:可以结合观察者模式实现中介者对象向同事对象发送通知的机制,以实现更加灵活的通信方式。

6.总结

中介者模式也存在缺点,如中介者对象的复杂性可能会随着系统的复杂性增加而增加,同时中介者对象可能会成为系统中的瓶颈。

相关文章:

设计模式 20 中介者模式 Mediator Pattern

设计模式 20 中介者模式 Mediator Pattern 1.定义 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为型设计模式&#xff0c;它通过封装对象之间的交互&#xff0c;促进对象之间的解耦合。中介者模式的核心思想是引入一个中介者对象&#xff0c;将系统中对象之间…...

在 C++ 中,p->name 和 p.name 的效果并不相同。它们用于不同的情况,取决于你是否通过指针访问结构体成员。

p->name&#xff1a;这是指针访问运算符&#xff08;箭头运算符&#xff09;。当 p 是一个指向结构体的指针时&#xff0c;用 p->name 来访问结构体的成员。 student* p &stu; // p 是一个指向 student 类型的指针 cout << p->name << endl; // 通过…...

C++基础:多态

多态相关 多态继承重写父类的虚函数多态的体现,父类的引用指向子类对象的空间虚函数可以实现,也可以不实现,不实现必须要有初始值存在未定义的虚函数的类为抽象类.抽象类不能实例化对象;(animal父类不能实例化对象)如果父类中的函数非虚函数,则会调用父类中的函数//多态的体现…...

移除元素(算法题)

文章目录 移除元素解题思路 移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并原地修改输入数组。 元素的顺序可以改变。…...

电商场景的视频动效

AtomoVideo:AIGC赋能下的电商视频动效生成本文分享阿里妈妈视频 AIGC(AtomoVideo等) 赋能视频广告创意的探索和实践。通过基于扩散模型的视频生成技术,结合可控生成技术,使静态电商图片能够栩栩如生地“动”起来,实现了在电商领域的视频 AIGC 应用落地。https://mp.weixi…...

Windows操作系统基本知识整理

目录 引言 一、Windows操作系统的发展历史 1.1 Windows 1.0到Windows 3.0 1.2 Windows 95到Windows Me 1.3 Windows NT到Windows 2000 1.4 Windows XP到Windows 7 1.5 Windows 8到Windows 10 二、Windows操作系统的核心组件 2.1 内核 2.2 文件系统 2.3 图形用户界面&…...

Vue 状态管理深入研究:Vuex 和 Pinia 的原理与实践对比

推荐一个AI网站&#xff0c;免费使用豆包AI模型&#xff0c;快去白嫖&#x1f449;海鲸AI &#x1f44b; 引言 在 Vue.js 应用程序中&#xff0c;状态管理是一个至关重要的方面。它有助于集中管理应用的状态&#xff0c;使组件之间的数据共享更加高效和可维护。Vuex 和 Pinia …...

【三数之和】python,排序+双指针

暴力搜索3次方的时间复杂度&#xff0c;大抵超时 遇到不会先排序 排序双指针 上题解 照做 class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:res[]nlen(nums)#排序降低复杂度nums.sort()k0#留两个位置给双指针i,jfor k in range(n-2):if nums[k]…...

TCP通信实现(服务端与客户端)

TCP通信实现&#xff08;服务器端) 案例 // TCP 通信的服务器端#include <stdio.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h>int main() {// 1.创建socket(用于监听的套接字)int lfd socket(AF_…...

安装appium自动化测试环境,我自己的版本信息

教程来自&#xff1a;Appium原理与安装 - 白月黑羽 我的软件的版本&#xff1a; 安装是选择为自己安装而不是选all user pip install appium-python-client命令在项目根目录下安装appium-python-client sdk的话最简单的安装方式就是去Android官网下一个android studio然后在…...

【讲解下Web前端三大主流的框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

视频监控平台AS-V1000产品介绍:账户或用户数据的导入和导出功能介绍

目录 一、功能描述 &#xff08;一&#xff09;导入功能定义 &#xff08;二&#xff09;导出功能定义 二、用户数据的导入导出的作用 三、AS-V1000新版本的导出和导入功能介绍 &#xff08;一&#xff09;功能主界面 &#xff08;二&#xff09;导出功能 1、导出操作 …...

markdown画时序图的时候,如何自动显示每一条时序的序号

1: 现象描述 今天画时序图的时候&#xff0c;发现时序上面没有显示序号&#xff0c;看起来不够清晰&#xff0c;只有单纯的说明; 如下图所示 刚测试CSDN的时序图&#xff0c;默认是带序号的&#xff0c;看起来和实际使用的markdown工具有关系&#xff1b; 2&#xff1a;解决办…...

朴素贝叶斯

经典三门问题 问题 一种说法(直觉派) 另一种说法(贝叶斯派) 注意P(B)1, 已经知道路人抽中的就是绿豆 三门问题在网上争端比较大,分为直觉派和贝叶斯派,最后一个程序员出来写程序跑了一遍,发现就是贝叶斯派 朴素贝叶斯的直观理解 在X的条件下分别等于0~9的概率 注意之前我们讲的…...

【软件设计师】——10.面向对象技术

目录 10.1 基本概念 10.2设计原则 10.3 设计模式的概念与分类 10.4 创建型模式 10.4.1 Singleton 单例模式 10.4.2 Builder 构建器模式 10.4.3 Abstract Factory 抽象工厂模式 10.4.4 Prototype原型模式 10.4.5 Factory Method工厂方法模式 10.5 结构型模式 10.5.1 A…...

唐山无人机航拍,唐山无人机建模,唐山数据孪生

随着数字经济发展&#xff0c;各地逐渐兴起了无人机低空经济&#xff1b;尤其是无人机航拍&#xff0c;无人机建模&#xff1b;目前技术很成熟&#xff1b;比如水利部提出的数字孪生&#xff0c;四预的实现&#xff0c;都要通过无人机采集底层数据&#xff1b; 目前无人机建模…...

vue中分页查询的实现

在 Vue 中实现分页查询可以提升大型数据集的加载和显示效率。本文将逐步介绍如何使用 Vuex 状态管理和 axios HTTP 请求库来实现 Vue 分页查询。 1. 在 Vuex 中创建分页状态 首先&#xff0c;在 Vuex 状态管理中创建分页状态&#xff0c;该状态将存储每页的记录数、当前页码和…...

类 和 对象(二)

构造方法 接上篇&#xff0c;若每次都想下面的setDate方法给对象初始化&#xff0c;未免比较麻烦&#xff0c;那有什么方法可以让初始化更加简便呢&#xff1f; public void setDate(int year, int month, int day){this.year year;this.month month;this.day day;}答&#…...

buu[HCTF 2018]WarmUp(代码审计)

buu[HCTF 2018]WarmUp&#xff08;代码审计&#xff09; 题目 访问source.php <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source">"source.php","hint">"hint.php…...

力扣爆刷第145天之图论五连刷(dfs和bfs)

力扣爆刷第145天之图论五连刷&#xff08;dfs和bfs&#xff09; 文章目录 力扣爆刷第145天之图论五连刷&#xff08;dfs和bfs&#xff09;总结一、797. 所有可能的路径二、200. 岛屿数量三、695. 岛屿的最大面积四、1020. 飞地的数量五、130. 被围绕的区域 总结 dfs是一条路走…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

快刀集(1): 一刀斩断视频片头广告

一刀流&#xff1a;用一个简单脚本&#xff0c;秒杀视频片头广告&#xff0c;还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农&#xff0c;平时写代码之余看看电影、补补片&#xff0c;是再正常不过的事。 电影嘛&#xff0c;要沉浸&#xff0c;…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...