设计模式-行为型模式之中介者模式

news2025/1/30 16:19:32

2. 中介者模式

2.1. 模式动机

在用户与用户直接聊天的设计方案中,用户对象之间存在很强的 关联性,将导致系统出现如下问题:
  • 系统结构复杂

对象之间存在大量的相互关联和调用,若有一个对象发生变化,则需要跟踪和该对象关联的其他所有对象,并进行适当处理。
  • 对象可重用性差

由于一个对象和其他对象具有很强的关联,若没有其他对象的支持,一个对象很难被另一个系统或模块重用,这些对象表现出来更像一个不可分割的整体,职责较为混乱。
  • 系统扩展性低

增加一个新的对象需要在原有相关对象上增加引用,增加新的引用关系也需要调整原有对象,系统耦合度很高,对象操作很不灵活,扩展性差。
在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责。
对于一个模块,可能由很多对象构成,而且这些对象之间可能存在相互的引用,为了减少对象两两之间复杂的引用关系,使之成为一个松耦合的系统,我们需要使用中介者模式,这就是中介者模式的模式动机。

2.2. 模式定义

中介者模式(Mediator Pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式

2.3. 模式结构

中介者模式包含如下角色:

  • Mediator: 抽象中介者

  • ConcreteMediator: 具体中介者

  • Colleague: 抽象同事类

  • ConcreteColleague: 具体同事类

2.4. 时序图

2.5. 代码分析

#include <iostream>
#include "ConcreteColleagueA.h"
#include "ConcreteMediator.h"
#include "ConcreteColleagueB.h"

using namespace std;

int main(int argc, char *argv[])
{
    ConcreteColleagueA * pa = new ConcreteColleagueA();
    ConcreteColleagueB * pb = new ConcreteColleagueB();
    ConcreteMediator * pm = new ConcreteMediator();
    pm->registered(1,pa);
    pm->registered(2,pb);
    
    // sendmsg from a to b
    pa->sendmsg(2,"hello,i am a");
    // sendmsg from b to a
    pb->sendmsg(1,"hello,i am b");
    
    delete pa,pb,pm;
    return 0;
}
///
//  ConcreteMediator.h
//  Implementation of the Class ConcreteMediator
//  Created on:      07-十月-2014 21:30:47
//  Original author: colin
///

#if !defined(EA_8CECE546_61DD_456f_A3E7_D98BC078D8E8__INCLUDED_)
#define EA_8CECE546_61DD_456f_A3E7_D98BC078D8E8__INCLUDED_

#include "ConcreteColleagueB.h"
#include "Mediator.h"
#include "ConcreteColleagueA.h"
#include <map>
using namespace std;
class ConcreteMediator : public Mediator
{

public:
    ConcreteMediator();
    virtual ~ConcreteMediator();

    virtual void operation(int nWho,string str);
    virtual void registered(int nWho, Colleague * aColleague);
private:
    map<int,Colleague*> m_mpColleague;
};
#endif // !defined(EA_8CECE546_61DD_456f_A3E7_D98BC078D8E8__INCLUDED_)
///
//  ConcreteMediator.cpp
//  Implementation of the Class ConcreteMediator
//  Created on:      07-十月-2014 21:30:48
//  Original author: colin
///

#include "ConcreteMediator.h"
#include <map>
#include <iostream>
using namespace std;

ConcreteMediator::ConcreteMediator(){

}

ConcreteMediator::~ConcreteMediator(){

}

void ConcreteMediator::operation(int nWho,string str){
    map<int,Colleague*>::const_iterator itr = m_mpColleague.find(nWho);
    if(itr == m_mpColleague.end())
    {
        cout << "not found this colleague!" << endl;
        return;
    }
    
    Colleague* pc = itr->second;
    pc->receivemsg(str);
}


void ConcreteMediator::registered(int nWho,Colleague * aColleague){
    map<int,Colleague*>::const_iterator itr = m_mpColleague.find(nWho);
    if(itr == m_mpColleague.end())
    {
        m_mpColleague.insert(make_pair(nWho,aColleague));
        //同时将中介类暴露给colleague 
        aColleague->setMediator(this);
    }
}
///
//  ConcreteColleagueA.h
//  Implementation of the Class ConcreteColleagueA
//  Created on:      07-十月-2014 21:30:47
//  Original author: colin
///

#if !defined(EA_79979DD4_1E73_46db_A635_E3F516ACCE0A__INCLUDED_)
#define EA_79979DD4_1E73_46db_A635_E3F516ACCE0A__INCLUDED_

#include "Colleague.h"

class ConcreteColleagueA : public Colleague
{

public:
    ConcreteColleagueA();
    virtual ~ConcreteColleagueA();

    virtual void sendmsg(int toWho,string str);
    virtual void receivemsg(string str);

};
#endif // !defined(EA_79979DD4_1E73_46db_A635_E3F516ACCE0A__INCLUDED_)
///
//  ConcreteColleagueA.cpp
//  Implementation of the Class ConcreteColleagueA
//  Created on:      07-十月-2014 21:30:47
//  Original author: colin
///

#include "ConcreteColleagueA.h"
#include <iostream>
using namespace std;

ConcreteColleagueA::ConcreteColleagueA(){
}

ConcreteColleagueA::~ConcreteColleagueA(){
}

void ConcreteColleagueA::sendmsg(int toWho,string str){
    cout << "send msg from colleagueA,to:" << toWho << endl;
    m_pMediator->operation(toWho,str);
}

void ConcreteColleagueA::receivemsg(string str){
    cout << "ConcreteColleagueA reveivemsg:" << str <<endl;
}

运行结果:

2.6. 模式分析

中介者模式可以使对象之间的关系数量急剧减少。

中介者承担两方面的职责:

  • 中转作用(结构性)

通过中介者提供的中转作用,各个同事对象就不再需要显式引用其他同事,当需要和其他同事进行通信时,通过中介者即可。该中转作用属于中介者在结构上的支持。
  • 协调作用(行为性)

中介者可以更进一步的对同事之间的关系进行封装,同事可以一致地和中介者进行交互,而不需要指明中介者需要具体怎么做,中介者根据封装在自身内部的协调逻辑,对同事的请求进行进一步处理,将同事成员之间的关系行为进行分离和封装。该协调作用属于中介者在行为上的支持。

时序图

2.7. 实例

实例:虚拟聊天室

某论坛系统欲增加一个虚拟聊天室,允许论坛会员通过该聊天室进行信息交流,普通会员(CommonMember)可以给其他会员发送文本信息,钻石会员(DiamondMember)既可以给其他会员发送文本信息,还可以发送图片信息。该聊天室可以对不雅字符进行过滤,如“日”等字符;还可以对发送的图片大小进行控制。用中介者模式设计该虚拟聊天室。

2.8. 优点

中介者模式的优点

  • 简化了对象之间的交互。

  • 将各同事解耦。

  • 减少子类生成。

  • 可以简化各同事类的设计和实现。

2.9. 缺点

中介者模式的缺点

  • 在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

2.10. 适用环境

在以下情况下可以使用中介者模式:

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。

  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。

  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象。

  • 交互的公共行为,如果需要改变行为则可以增加新的中介者类。

2.11. 模式应用

MVC架构中控制器

Controller 作为一种中介者,它负责控制视图对象View和模型对象Model之间的交互。如在Struts中,Action就可以作为JSP页面与业务对象之间的中介者。

2.12. 模式扩展

中介者模式迪米特法则

  • 在中介者模式中,通过创造出一个中介者对象,将系统中有关的对象所引用的其他对象数目减少到最少,使得一个对象与其同事之间的相互作用被这个对象与中介者对象之间的相互作用所取代。因此,中介者模式就是迪米特法则的一个典型应用

中介者模式GUI开发

  • 中介者模式可以方便地应用于图形界面(GUI)开发中,在比较复杂的界面中可能存在多个界面组件之间的交互关系。

  • 对于这些复杂的交互关系,有时候我们可以引入一个中介者类,将这些交互的组件作为具体的同事类,将它们之间的引用和控制关系交由中介者负责,在一定程度上简化系统的交互,这也是中介者模式的常见应用之一。

2.13. 总结

  • 中介者模式用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式

  • 中介者模式包含四个角色抽象中介者用于定义一个接口,该接口用于与各同事对象之间的通信;具体中介者是抽象中介者的子类,通过协调各个同事对象来实现协作行为,了解并维护它的各个同事对象的引用;抽象同事类定义各同事的公有方法;具体同事类是抽象同事类的子类,每一个同事对象都引用一个中介者对象;每一个同事对象在需要和其他同事对象通信时,先与中介者通信,通过中介者来间接完成与其他同事类的通信;在具体同事类中实现了在抽象同事类中定义的方法。

  • 通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构,中介者承担了中转作用协调作用中介者类是中介者模式的核心,它对整个系统进行控制和协调,简化了对象之间的交互,还可以对对象间的交互进行进一步的控制。

  • 中介者模式的主要优点在于简化了对象之间的交互,将各同事解耦,还可以减少子类生成,对于复杂的对象之间的交互,通过引入中介者,可以简化各同事类的设计和实现;中介者模式主要缺点在于具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护

  • 中介者模式适用情况包括:系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解;一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象;想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

[上一节]设计模式-行为型模式之命令模式

[下一节]设计模式-行为型模式之观察者模式

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

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

相关文章

初识 MongoDB

文章目录 一、简介二、体系结构三、数据类型四、特点五、应用场景 提示&#xff1a;以下是本篇文章正文内容&#xff0c;MongoDB 系列学习将会持续更新 一、简介 MongoDB 是一个文档数据库&#xff0c;是由字段和值对&#xff08;field:value&#xff09;组成的数据结构&…

煤矿电子封条视频监控系统 yolov7

煤矿电子封条视频监控系统基于yolov7python网络模型视频AI智能分析技术&#xff0c;煤矿电子封条视频监控算法模型对现场皮带撕裂、跑偏、皮带异物、堆煤等设备异常状态实时监控分析自动识别预警。YOLOv7 的发展方向与当前主流的实时目标检测器不同&#xff0c;研究团队希望它能…

(原创)Flutter基础入门:装饰器Decoration

前言 作为一个Android开发&#xff0c;最近打算把自己学的Flutter相关知识做个积累&#xff0c;所以这会是一个系列的博客。里面讲的都会是一些Flutter相关的知识&#xff0c;有基础的&#xff0c;也有比较深入的&#xff0c;由浅入深嘛。 那么今天作为开篇&#xff0c;就先讲…

经典回顾丨同为科技(TOWE)在2008年奥运场馆防雷建设中都做了什么?

针对大型体育赛事场馆防雷建设工作非常重要&#xff0c;这是因为大型体育赛事通常吸引了大量的观众和运动员聚集&#xff0c;一旦场馆遭受雷击&#xff0c;可能会造成严重的伤亡和财产损失。如今&#xff0c;大型体育赛事的场馆都会配备防雷设施&#xff0c;如建筑物避雷针、接…

代理设计模式解读

目录 代理模式的基本介绍 静态代理 静态代码模式的基本介绍 应用实例 思路分析图解(类图) 代码实战 静态代理优缺点 动态代理 动态代理模式的基本介绍 JDK 中生成代理对象的 API 代码实战 Cglib 代理 Cglib 代理模式的基本介绍 Cglib 代理模式实现步骤 Cglib 代理模…

同为科技(TOWE)机柜PDU电源插头类型详解

机柜PDU电源插座作为机房服务器众多设备运行的“最后一米”也是最为密切的电源配件&#xff0c;专用于精细保护单相交流供电的敏感设备&#xff0c;其品质好坏直接影响到各个设备的正常运行。机柜PDU电源管理器是由插头、线缆、主体三个部分组成&#xff0c;其中电源插头可以分…

leetcode24. 两两交换链表中的节点

给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4] 输出&#xff1a;[2,1…

什么是机器学习?

目录 简介 机器学习可以做什么 机器学习未来的趋势 总结 简介 机器学习是一种人工智能领域中的技术&#xff0c;其主要目的是让计算机能够自动进行模式识别、数据分析和预测。 机器学习的起源可以追溯到20世纪50年代&#xff0c;当时美国的Arthur Samuel在一篇论文中提出了相关…

(转)使用Midjourney进行图生图

原文链接:使用Midjourney进行AI绘画的基础手册-虎课网 接下来,我们讲一下,如果使用Midjourney的垫图功能,创作相同风格的图片 第一步: 1、打开discord,查看自己的服务器 2、我们双击“+”,来上传图片,图片上传后,按下enter发送图片; 图片发送成功后,点击图片放大…

不得不说的创建型模式-单例模式

单例模式是创建型模式的一种&#xff0c;它的作用是确保一个类只有一个实例&#xff0c;并提供全局访问点。单例模式通常用于管理共享资源&#xff0c;如配置文件、数据库连接池等&#xff0c;它可以保证这些资源只被创建一次&#xff0c;并且可以被全局共享。 下面是一个使用C…

AI 智能会有自主意识吗?会不会伤害人?

随着科技的高速发展&#xff0c;人工智能已逐渐融入我们的日常生活。从智能家居设备到自动驾驶汽车&#xff0c;人工智能的应用领域越来越广泛。然而&#xff0c;在这个趋势背后&#xff0c;我们面临着一个极具争议的问题&#xff1a;人工智能是否会觉醒自我意识&#xff1f;我…

程序员阿里三面无理由挂了,被HR一句话噎死,网友:这可是阿里啊

进入互联网大厂一般都是“过五关斩六将”&#xff0c;难度堪比西天取经&#xff0c;但当你真正面对这些大厂的面试时&#xff0c;有时候又会被其中的神操作弄的很是蒙圈。 近日&#xff0c;某位程序员发帖称&#xff0c;自己去阿里面试&#xff0c;三面都过了&#xff0c;却被…

近期遇到的vscode 插件开发的问题,when表达式,正则匹配路径

前言 最近在修改dbt插件的时候&#xff0c;遇到了几个比较奇怪的问题&#xff0c;猜测应该是因为跟新了VSCode导致的。 这里稍微记录一下&#xff0c;如果能帮助其他的同学&#xff0c;那就太值啦。 when 正则表达式 之前有在packgae.json 中使用 when 的正则表达式&#xf…

文章修改润色软件-中文文章自动润色

在今天这个信息爆炸的时代&#xff0c;写作已经成为了生活和工作中不可或缺的一部分。无论是企业宣传材料、项目报告、还是日常沟通&#xff0c;我们都需要写作来表达自己的意见和观点。但是&#xff0c;对于大多数人来说&#xff0c;写作带来的不仅仅是创作的乐趣&#xff0c;…

Nacos 1.4.x 升级至 2.x 详细步骤及遇到的问题

此前使用的nacos版本是1.4.5&#xff0c;现在nacos最新版本为2.2.2&#xff0c;且修复了旧版本的一些安全问题&#xff0c;下面把详细的升级步骤记录一下&#xff0c;大家一起学习。主要参照了nacos官方升级文档&#xff1a;https://nacos.io/zh-cn/docs/v2/upgrading/2.0.0-up…

MongoDB 分片集群架构中的分片策略

一、分片集群架构 1-1、分片简介 分片&#xff08;shard&#xff09;是指在将数据进行水平切分之后&#xff0c;将其存储到多个不同的服务器节点上的一种扩展方式。分片在概念上非常类似于应用开发中的“水平分表”。不同的点在于&#xff0c;MongoDB本身就自带了分片管理的能…

【Linux】基于单例模式懒汉实现方式的线程池

目录 一、LockGuard.hpp 二、Task.hpp 三、Thread.hpp 四、ThreadPool.hpp 一、LockGuard.hpp #pragma once #include <iostream> #include <pthread.h> class Mutex//锁的对象 { public:Mutex(pthread_mutex_t* lock_pnullptr):_lock_p(lock_p){}~Mutex(){}v…

设计模式-看懂UML类图和时序图

这里不会将UML的各种元素都提到&#xff0c;只讲类图中各个类之间的关系&#xff1b; 能看懂类图中各个类之间的线条、箭头代表什么意思后&#xff0c;也就足够应对 日常的工作和交流&#xff1b; 同时&#xff0c;应该能将类图所表达的含义和最终的代码对应起来&#xff1b;1.…

Qt音视频开发39-海康sdk回调拿到数据GPU绘制的实现

一、前言 采用海康的sdk做开发&#xff0c;最简单最容易的方式就是传入句柄&#xff08;windows和linux都支持/很多人以为只有windows才支持&#xff09;即可&#xff0c;这种方式不用自己处理绘制&#xff0c;全部交给了sdk去处理&#xff0c;所以cpu的占用是最低的&#xff…

ERTEC200P-2 PROFINET设备完全开发手册(8-1)

8.1 IRT通讯实验 这里我们使用APP3 IsoApp&#xff0c;修改源代码usrapp_cfg.h的宏为 #define EXAMPL_DEV_CONFIG_VERSION 3 使能App3&#xff0c;对应的主程序为“usriod_main_isoapp.c” 编译后下载运行。打开4.2建立的TIA项目&#xff0c;添加等时模式组织块&#xff0c…