设计模式8之中介者模式

2022-05-05 17:42:24 浏览数 (1)

背景

有这样一个场景,如果你有很多朋友,朋友与朋友之间也是朋友。如果你的QQ号码变化,你的所有朋友都需要知道,你会告诉你的朋友你的QQ号码变了,朋友再告诉他的朋友。这样所有的朋友都需要相互通知你的QQ号码变了,这样牵一发动全身,耦合性非常大。

网状结构

为了降低之间的耦合性,可以将网状结构改成星形模式。这里就需要一个中介者,负责告知所有的朋友。

星形结构

这种形式后面就发展成了中介者模式。

什么是中介者模式

“Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly,and it lets you vary their interaction independently.(用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。) ”

中介者模式中,有一个中介对象用来封装一系列的对象之间的交互,使原有的对象之间的耦合性更松散。

使用中介者模式可以使对像之间的一对多关系简化为一对一的关系,提高了系统的灵活性。

但是如果对象太多,会导致中介者逻辑更加复杂化,中介者的维护也需要一定的成本。

中介者模式主要由下面几个要素组成:

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  • 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

组成元素

代码示例

我们按照上图的关系来写代码

Mediator

代码语言:javascript复制
public abstract class Mediator {
    public abstract void register(Colleague colleague);
    public abstract void relay(Colleague cl); //转发
}

ConcreteMediator

Colleague

ConcreteColleague1

ConcreteColleague2同上。

我们来测试下:

测试结果:

代码语言:javascript复制
具体同事类1发出请求。
具体同事类2收到请求。
------------
具体同事类2发出请求。
具体同事类1收到请求。

代码解释

首先我们创建一个具体中介者对象,具体同事对象1,具体同事对象2。然后执行:

代码语言:javascript复制
md.register(c1);
md.register(c2);

这时List中会存入ConcreteColleague1ConcreteColleague2的对象。

然后执行:

代码语言:javascript复制
c1.send()

send()方法内部打印【具体同事类1发出请求。】。然后执行中介者的转发方法:

代码语言:javascript复制
mediator.relay(this);

这个方法会拿取List集合中除自身调用者的Colleague对象。然后执行除自身的所有对象的receive()方法。

同事与同事之间的通信交给了中介者去做了。

关于中介者模式的思考

我们什么时候需要使用中介者模式呢?

当多个对象之间出现紧密耦合的情况,紧密耦合的标准是:在类图中出现了蜘蛛网状结构。在这种情况下一定要考虑使用中介者模式,这有利于把蜘蛛网梳理为星型结构,使原本复杂混乱的关系变得清晰简单。

然而只用中介者模式也需要量力而行,就如文章同开头说的,使用中介者模式会使中介者类的代码逻辑更为复杂。所以在使用时需要有取舍。

其实我们常用的的MVC模型也是使用了中介者模式,其中的C(Controller)就是一个中介者,叫做前端控制器(Front Controller),它的作用就是把M(Model,业务逻辑)和V(View,视图)隔离开, 协调M和V协同工作,把M运行的结果和V代表的视图融合成一个前端可以展示的页面,减少 M和V的依赖关系。

0 人点赞