目录

一、定义

二、未使用/使用中介者模式对比

三、角色分析

四、中介者模式案例分析

五、总结


一、定义

中介者模式,其实就是定义了一个具体中介者对象来协调各个子系统的交互依赖关系,使得各个子系统之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式属于行为型模式。

在现实生活中,有很多中介者模式的身影,例如QQ游戏平台,聊天室、QQ群、短信平台和房产中介。我们使用的QQ聊天室和短信平台其实就是充当了一个中介者角色,通过这个平台我们就可以与其他QQ用户进行聊天或者发短信,并不需要依赖其他用户。还有就是我们熟悉的MVC三层架构中: Controller控制层就是Model模型层和View视图层之间的中介者。

二、未使用/使用中介者模式对比

  • 如果不使用中介者模式,让各个子系统之间相互发生依赖关系的话,那么系统耦合性会比较大, 也不利于系统维护以及开发人员的理解;
  • 使用中介者模式之后,将这些依赖关系断开,引入一个中介者用于协调他们之间的关系,让各个子系统只与中介者发生依赖,三个对象A、B、C都相互都不依赖;

三、角色分析

中介者模式的通用类图如下所示:

下面我们分析一下中介者模式涉及的几个角色:

  • 抽象中介者角色:提供了同事对象注册与转发同事对象信息的抽象方法,用于各同事对象之间的交互;
  • 具体中介者角色:实现了抽象中介角色定义的抽象方法,一般聚合了所有的具体同事类,负责协调各同事对象的行为以完成协作;
  • 抽象同事角色:抽象同事类,定义了具体同事角色共同的行为;
  • 具体同事角色:一般会有多个具体同事角色,每个具体同事角色都只知道和中介者角色发生依赖,并不知道其他同事角色的行为方法;

四、中介者模式案例分析

我们使用生活中必不可少的QQ聊天程序作为中介者模式讲解的示例,这里的“中介者”其实就是 QQ 服务器,而我们这些各个用户其实就是具体同事类。类图如下:

首先定义我们的抽象中介者角色,它定义了同事对象到中介者对象的接口,具体代码如下:

public abstract class Mediator {/*** 注册同事方法*/public abstract void register(String key, Colleague colleague);/*** 发送消息*/public abstract void sendMessage(String key);}

抽象中介者提供了两个方法:

  • 注册同事方法;
  • 发送消息方法;

下面我们定义抽象同事类角色,它主要定义了具体同事角色共同的行为,即发送消息、接收消息,把它类比成聊天的我们,那么我们肯定也就是拥有发送消息、接收消息的行为:

public abstract class Colleague {/*** 发送消息*/public abstract void sendMessage();/*** 接收消息*/public abstract void receiveMessage();}

下面我们定义两个使用QQ服务器的角色:UserA和UserB,它们充当具体同事类的角色,具体代码如下:

public class QQUserA extends Colleague {private static final String USER_A_REGISTER_KEY = "userA";private static final String USER_B_REGISTER_KEY = "userB";/*** 持有一个抽象中介者对象引用*/private Mediator mediator;public QQUserA(Mediator mediator) {this.mediator = mediator;//注册到中介中容器中mediator.register(USER_A_REGISTER_KEY, this);}@Overridepublic void sendMessage() {System.out.println("用户A发出消息...");//UserA发送消息的时候,通过中介者发送消息,实际上调用的是UserB的接收消息方法mediator.sendMessage(USER_B_REGISTER_KEY);}@Overridepublic void receiveMessage() {System.out.println("用户A接收到消息...");}
}public class QQUserB extends Colleague {/*** 持有一个抽象中介者对象引用*/private Mediator mediator;private static final String USER_A_REGISTER_KEY = "userA";private static final String USER_B_REGISTER_KEY = "userB";public QQUserB(Mediator mediator) {this.mediator = mediator;//注册到中介中容器中mediator.register(USER_B_REGISTER_KEY, this);}@Overridepublic void sendMessage() {System.out.println("用户B发出消息...");//UserB发送消息的时候,通过中介者发送消息,实际上调用的是UserA的接收消息方法mediator.sendMessage(USER_A_REGISTER_KEY);}@Overridepublic void receiveMessage() {System.out.println("用户B接收到消息...");}
}

可以看到,我们的具体同事类都持有一个抽象中介者对象引用,并在发送完消息后,通过中介者角色调用另外一个用户的接收消息方法,实现了两个用户之间的通信。

当然,抽象中介者的引用也可以放在父类-抽象同事类中。

下面还差一个具体的中介者对象,也就是我们前面提到的QQ聊天服务器,具体代码如下:

public class QQServer extends Mediator {/*** 具体中介者类持有多个同事类对象引用* 这里使用Map保存,当然也可以使用List或者其他集合进行保存*/private Map<String, Colleague> colleagueMap = new HashMap<>();@Overridepublic void register(String key, Colleague colleague) {colleagueMap.put(key, colleague);}@Overridepublic void sendMessage(String key) {Colleague colleague = colleagueMap.get(key);if (null != colleague) {colleague.receiveMessage();}}
}

具体中介者内部使用一个容器,可以是List,也可以是Map或者其他容器,用于存放所有的具体同事类的引用,在前面的具体同事类的构造方法中,在创建具体同事类的时候,就会将他们注册到中介者的容器里面,并且具体的中介者【QQ聊天服务器】提供了一个转发消息的方法sendMessage(),实际上就是调用具体同事类的接收消息方法,完成消息的转发。

最后,我们看下客户端怎么调用:

public class Client {public static void main(String[] args) {Mediator qqServer = new QQServer();Colleague userA = new QQUserA(qqServer);Colleague userB = new QQUserB(qqServer);//用户A发出消息userA.sendMessage();System.out.println("==============");//用户B发出消息userB.sendMessage();}
}

运行结果如下:

可以看到,通过具体中介者对象【QQ聊天服务器】,解耦了各个同事类【UserA、UserB...】之间相互依赖的场景,具体同事类直接都与中介者对象发生关联。

五、总结

中介者模式的优点:

  • 降低了对象之间的耦合性,使得对象易于独立地被复用;
  • 将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展;
  • 符合迪米特原则;

中介者模式的缺点:

  • 具体中介者角色承担了较多的职责,一旦出现了问题,整个系统将会受到比较大的影响;
  • 具体的中介者比较庞大,难以维护;
  • 新增加一个同事类时,不得不去修改抽象中介者类和具体中介者类,此时可以使用观察者模式和状态模式来解决这个问题;

中介者模式的适用场景:

  • 当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时,可以考虑使用中介者模式;
  • 当想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类时,可以考虑使用中介者模式;

设计模式 ( 十九) 中介者模式相关推荐

  1. 设计模式十二之组合模式

    设计模式十二之组合模式 1. 模式的定义与特点 1.1 模式的定义 1.2 模式的特点 1.3 模式的使用场景 2. 模式的结构与实现 2.1 模式的结构 2.2 模式的实现 3. 模式在开源软件中的 ...

  2. 【大话设计模式】模式十:中介者模式

    [引入] 国与国之间的关系,类似于对象与对象之间的关系,这就要求对象之间需要知道其他所有对象.但是对象之间大量的链接使得一个对象不可能在没有其他对象支持下工作,系统表现为一个不可分割的整体,降低其可复 ...

  3. C#设计模式之十七中介者模式(Mediator Pattern)【行为型】

    一.引言 今天我们开始讲"行为型"设计模式的第五个模式,该模式是[中介者模式],英文名称是:Mediator Pattern.还是老套路,先从名字上来看看."中介者模式& ...

  4. 《研磨设计模式》chap10 中介者模式Mediator(1)简介

    1. 使用场景 如果电脑没有主板,各个配件的关系为 有主板后: 2. 中介者模式简介:各对象通过中介者来交互 //Mediator.java public interface Mediator { p ...

  5. java mediator模式_设计模式之Mediator 中介者模式 - 解道Jdon

    设计模式目录 >> 当前页 设计模式之Mediator(中介者) 板桥里人 http://www.jdon.com 2002/05/05 Mediator中介者模式定义: 用一个中介对象来 ...

  6. 【Java开发】设计模式 17:中介者模式

    1 中介者模式介绍 中介者模式是一种行为设计模式,指用一个中介对象来封装一系列的对象交互. 中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互.在这个模式中,中介者 ...

  7. 设计模式学习笔记--中介者模式(详细笔记)

    文章目录 1. 概述 2. 使用实例 1. 概述 使用背景: 菜鸟教程 用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. ...

  8. 设计模式理解:中介者模式(Mediator)

    中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性.这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护. 两个类或者多个类之间存在相 ...

  9. 【原创】StreamInsight查询系列(十九)——查询模式之检测异常

    上篇文章介绍了查询模式中如何发现趋势,这篇博文将介绍StreamInsight中如何检测异常. 测试数据准备 为了方便测试查询,我们首先准备一个静态的测试数据源: var now = DateTime ...

  10. Net设计模式实例之中介者模式(Mediator Pattern)

    一.中介者模式简介(Brief Introduction) 中介者模式(Mediator Pattern),定义一个中介对象来封装系列对象之间的交互.中介者使各个对象不需要显示地相互引用,从而使其耦合 ...

最新文章

  1. matlab 自适应噪声对消,基于Matlab的RLS自适应语音噪声对消系统的设计与实现
  2. docker公共存储库_Docker实战001:简单的认识下docker
  3. JavaScript 是按值传递还是按引用传递的
  4. jQuery基础集锦——插件开发
  5. “差不多先生”姚劲波和不再神奇的58同城
  6. iphone win7无法识别_win7系统电脑插入苹果设备提示“无法识别IOS设备”的原因和解决方法...
  7. 5. 倒车入库+侧方位停车(仿真)
  8. 读史可以明智_为什么拥抱传统是明智的
  9. 如何取得销售订单中订单货币和本位币之间的汇率 (exchange rate)
  10. 大家小心 日本公司淘宝天猫阿里巴巴行为异常 我购买的业务已经被关闭
  11. 小狗钱钱2-读书笔记
  12. JS 流行库(五):Swiper
  13. Perfect Office Manner for Secretary 完美文秘办公礼仪
  14. 【工具】60 个相见恨晚的神器工具
  15. ethtool netlink 框架原理浅析
  16. 【在线支付】在线支付代码详解
  17. 可以给我写一个java语音外呼机器人代码吗
  18. FreeeBSD磁盘分区格式
  19. 亚马逊云AWS认证助理工程师题库第四题
  20. python巴特沃斯滤波器_butterworth-实时数字巴特沃斯IIR滤波器-Kei Imada

热门文章

  1. CNN是如何一层一层'理解'图像信息的
  2. 极客大学产品经理训练营 产品思维和产品意识(上) 第3课总结
  3. 极客大学架构师训练营 大数据 GFS、MapReduce、BigTable,Hadoop HDFS Yarn HiveQL 第12次作业
  4. mysql驱动是什么文件_Oracle数据库11g JDBC驱动程序 – 这么多文件?他们的意思是什么?...
  5. 8月7日晚八点分享-推荐系统面试/概览
  6. 编程计算二叉树中某结点的层数
  7. warning: control may reach end of non-void function [-Wreturn-type]
  8. Optional Interview with Benny the Irish Polyglot abo---coursera课程Learn how to learn
  9. 借助Haproxy_exporter实现对MarathonLb的流量和负载实例业务的可用状态监控-续
  10. 数据类型、变量和数组