设计模式18-中介者模式

news2024/12/28 12:02:01

设计模式18-中介者模式(Mediator)

  • 动机
  • 定义
  • 结构
      • 类图解释:
      • 交互方式:
      • 左边流程图
      • 右边流程图
      • 联系中介者模式
  • C++代码推导
  • 优缺点
  • 应用
  • 总结

动机

  • 在软件构建过程中,经常会出现多个对象互相关联交互的情况。他们之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。
  • 在这种情况下,我们可使用一个中介对象来管理对象间的关联关系。避免相互的对象之间的紧耦合引用关系。从而更好地抵御外界的变化。
  • 在复杂系统中,各个对象之间可能会有多种多样的直接相互依赖关系,导致系统变得难以理解和维护。中介者模式通过引入一个中介者对象,将对象之间的复杂交互逻辑进行集中管理,从而降低各个对象之间的耦合度,使系统更加易于维护和扩展。

定义

  • 用一个中介对象来封装(封装变化)一系列的对象交互。终结者使各对象不需要显示的相互引用(编译时依赖变成运行时依赖),从而使其耦合松散也可以独立的改变他们之间的交互。–《设计模式》GOF
  • 中介者模式定义了一个中介对象,该对象封装了对象之间的交互方式,使得对象之间不再需要显式地相互引用,从而使其耦合松散,且可以独立地改变它们之间的交互。

结构

在这里插入图片描述

这张图片展示的是设计模式中的一种经典结构——**中介者模式(Mediator Pattern)**的类图表示。中介者模式用于减少系统中对象之间的直接交互,通过引入一个中介者对象来协调它们之间的行为。这个模式特别适用于系统中对象之间存在大量复杂交互,并且这些交互导致代码难以理解和维护的场景。

类图解释:

  1. Mediator(中介者)

    • 是该结构的核心,它定义了一个接口,用于与各同事对象通信。
    • 在图中,Mediator是一个抽象类或接口,具体的中介者行为由ConcreteMediator类实现。
    • 通过与各个同事(Colleague)的交互,Mediator类能够控制或改变它们之间的交互方式。
  2. Colleague(同事)

    • 是系统中的其他对象,它们知道自己可以与其他同事对象交互,但具体交互是通过Mediator进行的。
    • Colleague是一个抽象类或接口,表示所有同事的共有特征和行为。
    • 在图中,ConcreteColleague1和ConcreteColleague2是Colleague的具体实现,它们分别代表不同的同事对象。
  3. ConcreteMediator(具体中介者)

    • 是Mediator接口的具体实现,包含了与同事对象交互的具体行为。
    • 它管理同事之间的直接交互,降低同事之间的耦合度。
  4. ConcreteColleague1 和 ConcreteColleague2(具体同事)

    • 是Colleague接口的具体实现,代表了系统中的具体业务对象。
    • 它们通过Mediator进行通信,而不是直接相互调用。

交互方式:

  • 同事对象(如ConcreteColleague1和ConcreteColleague2)之间不直接通信,而是通过中介者对象(ConcreteMediator)进行通信。
  • 中介者对象负责接收来自同事对象的请求,并根据需要转发给相应的同事对象。
  • 这种结构有助于减少同事对象之间的依赖,使系统更加灵活和易于维护。

在这里插入图片描述
这张图片中展示的两个流程图与中介者模式(Mediator Pattern)的结构图有一定的相似之处,尤其是在如何组织节点和它们之间的交互方面,尽管它们本身并不直接代表中介者模式的实现。

左边流程图

左边的流程图形成了一个环形结构,每个节点(1,2,3,4,5)通过箭头顺序连接,形成一个闭环。这个结构可以类比于一个系统中的对象或任务,它们按照一定的顺序或逻辑相互依赖和执行。然而,在这个简单的环形流程图中,并没有直接体现中介者角色的存在。但我们可以想象,如果这个流程图中包含更多的复杂交互或需要控制节点之间交互的逻辑,那么引入一个中介者对象来管理这些交互将是有益的。

右边流程图

右边的流程图则更接近于中介者模式的一个简化表示。中心节点“M”可以视为中介者的角色,它连接并管理着周围的四个节点(1, 2, 3, 4,5)。这些节点之间的交互不是直接进行的,而是通过“M”节点来协调。中心节点“M”的存在减少了其他节点之间的直接耦合,使得系统更加灵活和可扩展。此外,“M”节点周围的三个小圆圈可能代表不同的状态、条件或处理逻辑,这些都可以由中介者根据需要进行管理和控制。

联系中介者模式

在中介者模式中,Mediator(中介者)对象负责协调各个Colleague(同事)对象之间的交互,从而降低它们之间的耦合度。这张图片中的右边流程图通过中心节点“M”来协调其他节点的交互,与中介者模式中的Mediator角色相呼应。虽然左边的流程图没有直接展示中介者,但它可以通过增加中介者角色来改进和优化节点之间的交互方式。

综上所述,这张图片中的两个流程图可以在一定程度上反映中介者模式的思想和结构,尤其是在如何通过引入中介者来管理对象之间的交互和降低耦合度方面。

C++代码推导

以下是一个中介者模式的C++代码示例:

中介者接口:

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>

class Colleague;

class Mediator {
public:
    virtual void notify(Colleague* sender, const std::string& event) = 0;
    virtual void addColleague(Colleague* colleague) = 0;
    virtual ~Mediator() = default;
};

同事类:

class Colleague {
protected:
    Mediator* mediator;

public:
    Colleague(Mediator* mediator) : mediator(mediator) {}

    virtual void send(const std::string& message) = 0;
    virtual void receive(const std::string& message) = 0;

    virtual ~Colleague() = default;
};

具体同事类:

class ConcreteColleague1 : public Colleague {
public:
    ConcreteColleague1(Mediator* mediator) : Colleague(mediator) {}

    void send(const std::string& message) override {
        std::cout << "Colleague1 sends message: " << message << std::endl;
        mediator->notify(this, message);
    }

    void receive(const std::string& message) override {
        std::cout << "Colleague1 receives message: " << message << std::endl;
    }
};

class ConcreteColleague2 : public Colleague {
public:
    ConcreteColleague2(Mediator* mediator) : Colleague(mediator) {}

    void send(const std::string& message) override {
        std::cout << "Colleague2 sends message: " << message << std::endl;
        mediator->notify(this, message);
    }

    void receive(const std::string& message) override {
        std::cout << "Colleague2 receives message: " << message << std::endl;
    }
};

具体中介者类:

class ConcreteMediator : public Mediator {
private:
    std::vector<Colleague*> colleagues;

public:
    void addColleague(Colleague* colleague) override {
        colleagues.push_back(colleague);
    }

    void notify(Colleague* sender, const std::string& event) override {
        for (auto colleague : colleagues) {
            if (colleague != sender) {
                colleague->receive(event);
            }
        }
    }
};

客户端代码:

int main() {
    ConcreteMediator* mediator = new ConcreteMediator();

    ConcreteColleague1* colleague1 = new ConcreteColleague1(mediator);
    ConcreteColleague2* colleague2 = new ConcreteColleague2(mediator);

    mediator->addColleague(colleague1);
    mediator->addColleague(colleague2);

    colleague1->send("Hello, colleague2!");
    colleague2->send("Hi, colleague1!");

    delete colleague1;
    delete colleague2;
    delete mediator;

    return 0;
}

优缺点

优点:

  1. 降低耦合:中介者模式通过引入中介者对象,使同事对象之间不再直接依赖,从而降低了对象之间的耦合度。
  2. 集中控制:中介者模式将交互逻辑集中在中介者中,使得修改和维护交互逻辑更加容易。
  3. 符合单一职责原则:中介者对象负责处理对象之间的交互,其他对象只关注自身的业务逻辑。

缺点:

  1. 中介者复杂化:随着系统中同事对象数量的增加,中介者对象可能会变得非常复杂,难以维护。
  2. 性能开销:所有的交互都通过中介者进行,可能会带来一定的性能开销。

应用

中介者模式在以下场景中应用较多:

  1. GUI系统:在复杂的GUI系统中,不同组件之间的交互可以通过中介者进行协调,避免组件之间的直接依赖。
  2. 网络通信:在网络通信中,可以通过中介者协调不同模块之间的数据传输和交互。
  3. 聊天室:在聊天室系统中,中介者可以负责转发消息、管理用户等

总结

  • 中介者模式通过引入中介者对象,将对象之间的交互逻辑集中管理,从而降低对象之间的耦合度。尽管中介者模式可以有效地简化对象之间的交互,但在实际应用中需要注意中介者对象的复杂度和性能开销。在适当的场景下使用中介者模式,可以显著提高系统的可维护性和灵活性。
  • 将多个对象间复杂的关联关系进行解耦。中介者模式将多个对象间的控制逻辑进行集中管理。变 “多个对象互相依赖” 为 “多个对象和一个中介者关联”。简化了系统的维护,抵御了可能的变化。
  • 随着控制逻辑的复杂化,中介者具体对象的实现可能相当复杂。这时候可以对中介的对象进行分解处理。为了避免中介者对象变得过于庞大和复杂,可以将中介者对象进行分解处理,将不同的交互逻辑委派给多个小的中介者,从而简化主中介者的实现。
  • 门面模式是解耦系统间单向的对象关联关系。中介者模式是解耦系统内各个对象之间(双向)的关联关系

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

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

相关文章

认真学习JVM几种类加载器

【1】类加载器的分类 JVM支持两种类型的类加载器 。分别为引导类加载器&#xff08;Bootstrap ClassLoader&#xff09;和自定义类加载器&#xff08;User-Defined ClassLoader&#xff09;&#xff08;JVM规范这样定义的&#xff09;。 从概念上来讲&#xff0c;自定义类加载…

轻闪PDF v2.14.9 解锁版下载及安装教程 (一款全能PDF转换器,支持自动补全标签)

前言 轻闪PDF(原傲软PDF编辑软件)是一款操作简单的全能PDF转换器,轻松实现PDF转换为Word,Excel或其他格式,以及PDF压缩,合并和图片文字识别OCR等功能.这款pdf编辑转换软件几乎支持所有常见文档格式,一键完成PDF与其他文档互相转换,并含有PDF合并,压缩,图片文字识别OCR等增值功…

[qt] 多线程应用01

源码: 点击此处 一 多线程应用 实现一个多线程的网络时间服务器&#xff0c;利用多线程功能的技术&#xff0c;为每个客户端返回当前的时间&#xff0c;并且在返回后自动退出。同时&#xff0c;服务器也会记录当前受到的请求次数。其实这相当于一个ntp时间服务器 二 服务器实…

C语言 | Leetcode C语言题解之第326题3的幂

题目&#xff1a; 题解&#xff1a; bool isPowerOfThree(int n){int count0;while(n){countn%3;n/3;}return count1?true:false;}

个人对TCP流量控制与拥塞控制的理解

TCP 协议和 UDP 协议 TCP 作为最常用的两大传输层协议之一&#xff0c;无疑是久经生产环境检验的。传输层有两个我们广泛使用的协议&#xff1a;UDP 协议、TCP 协议&#xff0c;我们一般会说前者是面向无连接的&#xff0c;后者是面向连接的。 这里的 “连接” 具体是什么意思…

Prometheus-v2.45.0 + 钉钉告警

目录 1. 创建一个钉钉内部群 2. 添加自定义机器人 3. 配置钉钉发送告警服务 4. 配置alertmanager&#xff0c;接入dingding 5. 配置告警消息发送模板 6. 修改配置规则文件 续接上篇&#xff1a;https://blog.csdn.net/Lzcsfg/article/details/140851688 相关软件包链接…

sqli-labs环境搭建以及部分sql注入

sqli-labs靶场搭建&#xff1a; 安装phpstudy并创建网页 初始化靶场 实现sql注入&#xff1a; less-1&#xff08;根据数据库的命令在超链接后输入?id1&#xff09; less-2&#xff08;如法炮制?id2&#xff09; less-3&#xff08;闭合单引号和括号&#xff09; less-9&am…

新增AI Copilot,DataEase开源数据可视化分析工具v2.9.0发布

2024年8月5日&#xff0c;人人可用的开源数据可视化分析工具DataEase正式发布v2.9.0版本。 这一版本的功能变动包括&#xff1a;导航栏新增Copilot入口&#xff0c;借助AI技术&#xff0c;通过自然语言交互实现即问即答&#xff0c;让数据分析更加直观和便捷&#xff1b;图表方…

vxe-pulldown下拉容器的使用,覆盖样式z-index来解决在Modal中初次显示在Modal的下层的问题。

1、官网的例子&#xff1a; 可以说这个vxe-pulldown用起来还是挺方便的。 2、代码&#xff1a; <template><div><vxe-pulldown ref"pulldownRef" popup-class-name"my-dropdown4" transfer><template #header><div class&quo…

FFMPEG 序列帧图片合成视频

需求&#xff1a; 将多张.png图片合成为视频 注意: 1需要Windows电脑 2将图片重命名 下载EXE 官网 https://ffmpeg.org/download.html#build-windows 解压后长这样 将图片和exe放在同一目录下 文件中找个空白地&#xff0c;Shift右键 进入PowerShell 输入命令: ./ffm…

Chapter 27 封装

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、基本概念二、私有成员 前言 在面向对象编程&#xff08;OOP&#xff09;中&#xff0c;封装是一个重要的概念&#xff0c;旨在保护数据并限制对对象内部状态的直接…

48天笔试训练错题——day41

目录 选择题 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 编程题 1. 五子棋 2. Emacs计算器 选择题 1. 当发生拥塞时&#xff0c;TCP 有个机制&#xff0c;会从慢开始进行发送。 1. 把慢开始的门限值设为当前窗口的一半&#xff0c;即 ssthresh 1/2 * 8 4 KB 2. 把拥塞窗…

【TS】declare 全局声明方式

declare关键字 declare是描述TS文件之外信息的一种机制&#xff0c;它的作用是告诉TS某个类型或变量已经存在&#xff0c;我们可以使用它声明全局变量、函数、类、接口、类型别名、类的属性或方法以及后面会介绍的模块与命名空间。 declare关键字用来告诉编译器&#xff0c;某…

【C语言】关于字符串函数的使用及模拟实现(2)

一、字符串的复制 1.1 库函数strcpy的使用 在函数strcpy中&#xff0c;函数的返回类型为char* &#xff0c;参数部分首先是指向目标地址的指针&#xff0c;其次是指向源地址的指针(由于源地址中内容不受影响&#xff0c;则可以使用const修饰)&#xff0c;函数所需的头文件为st…

51单片机—串口

一、 串口基本认知 串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&a…

#70结构体案例1(导师,学生,成绩)

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <string> using namespace std;#include "random"int get_random_num(int min,int max) {random_device rd;mt19937 gen(rd());uniform_int_distribution<> dis(min,max);int ra…

C语言实现常见O(N^2)的排序算法

目录 1.排序的概念及常见排序算法 1.1排序的概念 1.2常见的排序算法 2.常见O(N^2)排序算法的实现 2.1插入排序 2.1.1基本思想 2.1.2直接插入排序 2.1.2.1直接插入排序的特性 2.1.2.2直接插入排序算法实现 2.2选择排序 2.2.1基本思想 2.2.2直接选择排…

【电脑基础硬件】磁盘阵列

磁盘阵列 一、磁盘阵列概述作用&#xff1a;RAID级别&#xff1a; 二、Raid0Raid1 一、磁盘阵列概述 磁盘阵列&#xff08;Disk Array&#xff09;是一种将多个独立的磁盘驱动器组合起来形成一个逻辑单元的技术&#xff0c;目的是为了提高存储系统的性能、可靠性和可用性。磁盘…

关于儿童编程语言

青少年通常会通过Scratch或Python开始学习编程。在这两种语言中&#xff0c;代码的编写&#xff08;或者在Scratch中是构建&#xff09;方式类似于英语&#xff0c;这使得初学者更容易学习。Scratch的一个重要卖点是对视觉和运动感知学习者非常友好。这些代码块按颜色编码&…

亚信安全获国家信息安全服务(风险评估和安全工程类)二级资质

近日&#xff0c;亚信安全荣获由中国信息安全测评中心颁发的《国家信息安全测评信息安全服务资质证书—风险评估二级》和《国家信息安全测评信息安全服务资质证书—安全工程类二级》资质。亚信安全凭借综合实力和优秀的技术能力&#xff0c;成为为数不多的获得国家信息安全服务…