1. 中介者模式的概念

中介者模式(Mediator), 用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式的相互引用,从而使其耦合松散,而且可以独立地改变他们之间的交互。

上面这句话其实就是将两个会发生作用的对象通过一个中介来解耦和,这就是迪米特法则的体现。
在开发中,我们使用了像MVP、MVVM这样的代码结构,目的是为了减少界面层的代码逻辑,将界面和数据层分开,P层和VM层就像中介者一样,避免了两者间的直接交互。

2. UML图

浅学设计模式之中介者模式(18/23)_中介者模式


在上图中,我们把 ​​ConcreteColleague1​​​和 ​​ConcreteColleague2​​看成是两个不需要直接关联的对象。

来介绍这些对象:

  • ​Mediator​​​:抽象中介者角色
    定义了同事对象到中介者对象的接口,一般以抽象类的方式实现。
  • ​ConcreteMediator​​​:具体中介者角色,继承于抽象中介者
    实现了父类定义的方法,它从具体的同事对象接收消息,向具体同事对象发出命令。
  • ​Colleague​​​:抽象同事类角色,定义了中介者对象的接口
    它只知道中介者而不知道其他的同事对象。
  • ​ConcreteColleague​​ 具体同事类角色,继承于抽象同事类,每个具体同事类都知道本身在小范围内的行为,而不知道它在大范围内的目的。

来看看模板代码,我们实现的是两个互不直接关联的同事类,他们需要互相发送消息和接收消息,在中介者模式中的实现是这样的:

首先是抽象中介者类​​Mediator​​:

public abstract class Mediator {
/**
* 抽象中介方法、子类实现
* 定义一个抽象的发送消息方法,得到同事对象和发送信息
*/
public abstract void send(String message, Colleage colleage);
}

接着是具体中介者类:

public class ConcreteMediator extends Mediator {

protected ConcreteColleagueA concreteColleagueA;
protected ConcreteColleagueB concreteColleagueB;


public void setConcreteColleagueA(ConcreteColleagueA concreteColleagueA) {
this.concreteColleagueA = concreteColleagueA;
}

public void setConcreteColleagueB(ConcreteColleagueB concreteColleagueB) {
this.concreteColleagueB = concreteColleagueB;
}

@Override
public void send(String message, Colleage colleage) {
if (colleage == concreteColleagueA) {
concreteColleagueB.notify(message);
} else {
concreteColleagueA.notify(message);
}
}
}

它实现了同事类A和同事类B的关联。

接着来到我们的同事类中,首先需要他们的抽象类 Colleage:

public abstract class Colleage {
protected Mediator mediator; // 中介者对象

public Colleage(Mediator mediator) {
this.mediator = mediator;
}

}

它定义了Colleage系列需要实现的方法,并且持有一个中介者对象,(这里有点像MVP中V层需要持有P层的引用一样),接着实现子类:

public class ConcreteColleagueA extends Colleage {

public ConcreteColleagueA(Mediator mediator) {
super(mediator);
}

//发送信息时通常是中介者发出去的
public void send(String message) {
mediator.send(message, this);
}

public void notify(String message) {
System.out.println(message);
}
}

这里省略同事类B,接着我们在客户端代码中看下A和B是怎么通过中介者发送消息的:

public class MediatorMain {
public static void mian(String[] main) {
ConcreteMediator m = new ConcreteMediator();

//让两个具体同事类认识中介者对象
ConcreteColleagueA c1 = new ConcreteColleagueA(m);
ConcreteColleagueB c2 = new ConcreteColleagueB(m);

//让中介者认识各个具体同事类对象
m.setConcreteColleagueA(c1);
m.setConcreteColleagueB(c2);

//具体的同事类对象的发送信息都是通过中介者转发
c1.send("吃过饭了吗?");
c2.send("没有, 你请客吗?");
}
}

由于有了​​Mediator​​,使得ConcreteColleagueA和ConcreteColleagueB在发送消息和接收消息时其实是通过中介者来完成的,这就减少了他们之间的耦合。

3. 中介者模式在Android的应用

3.1 MVP、MVVM

正如开篇所说,我认为 MVPMVVM的代码结构就很符合中介者模式。
创始者认为在Android开发中,主要分为 视图层和数据层,我们通过触摸视图,那么P层可能会产生一些网络请求,M层的数据产生了变化,这个时候 P层就是 M层和V层的中介者。P层的存在是为了解耦M层和V层。

3.2 UI控件本身

UI控件本身就是中介者。
在程序中,我们是要去通过改变数据集,让程序不断的运行下去,比如在 注册模块中,我们需要让程序记住我们的账号和密码,但是作为用户,我们本身是不能直接去修改账号和密码的,这个时候 ​​​EditText​​就作为中介者,我们通过在输入框上输入后,点击确认按钮,EditText将内容上传到后台。

那这样一比喻,你就会感觉中介者其实还挺多的,它与我们开发密切相关,知识我们使用了MVP、MVVM、MVC这样的架构显式的体现了出来。

4. 小结

中介者模式完美的体现了 迪米特原则—如果两个对象不需要直接联系,那就把它们完全分割开,互不持有。这是它最大的优点,解耦。

它的缺点也很明显,我们知道MVP和MVC的缺点,所以本质上也是中介者的缺点:

  • 在所涉及的对象较少时,使用中介者其实就是增加了文件和多余的操作,这样其实会使得原本清晰的逻辑变得复杂
  • 在所涉及的对象比较多时,势必会导致中介者代码的增加,如果不善加控制,会导致中介者的代码远远多余它所涉及的对象代码本身,变得十分臃肿