动机

在软件构建过程中,经常会出现多个对象互相关联交互的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。

在这种情况下,我们可以使用一个“中介对象”来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。

举个例子:UI元素 <-> DataModel

  • 当界面元素更改时,DataModel跟着更改;当DataModel更改时,界面也跟着更改
  • 界面控件存一个DataModel,DataModel里也存一个界面控件,这很复杂,也紧耦合
  • 一般情况下,会定义一个数据绑定类型,来管理这两者的关系
    • 这个数据绑定类型就是中介者,它会同时依赖界面控件与DataModel
    • 并提供一种协议,程序员去编写这些协议(绑定规则),数据绑定类型就会在运行时,将消息派发下去,实现两者之间的交互

例子:有5个对象,它们之间的依赖关系如下图所示
image.png
而中介者模式,就是提出一个对象,来解耦它们之间的依赖关系

  • 中介者与它们之间建立双向依赖关系

image.png

  • 1如果要调用3,1先通知M,让M调用3
  • 中介者模式常与订阅者模式一起使用。1把消息发给M,由M派发给相关订阅者,从而实现消息的传递

模式定义

用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显示的相互引用(编译时依赖 转成 运行时依赖),从而使其耦合松散(管理变化),而且可以独立地改变它们之间的交互——《设计模式》GoF

  • 显示引用是什么意思?就是编译时依赖。编译时依赖不利于未来的变化,依赖肯定是要依赖的,但我们可以转成运行时依赖。比如最经典的依赖倒置原则
  • 中介者设计模式的应用,一定是系统出现了大量的多个对象相互关联的情况,造成了复杂的引用关系。如果才一两个,那么是没有必要引出中介者模式的

结构

image.png

  • 依赖解耦:ConcreteColleague1ConcreteColleague2之间没有依赖关系。而是ConcreteMediator依赖了两者,在ConcreteMediator内部实现了两者的关联
  • Mediator是抽象的中介者,Colleague内有一个Mediator的指针

要点总结

将多个对象间复杂的关联关系解耦,Mediator模式将多个对象间的控制逻辑进行集中管理,变“多个对象互相关联”为“多个对象和一个中介者关联”,简化了系统的维护,抵御了可能的变化。

随着控制逻辑的复杂化,Mediator具体对象的实现可能相当复杂。这时候可以对Mediator对象进行分解处理。

门面模式是解耦系统间(单向)的对象关联关系;而中介者模式是解耦系统内各个对象之间(双向)的关联关系。