中介者模式-Mediator Pattern
序言
想象一个没有塔台的机场:每一架飞机都需要直接与其他所有飞机通信,告诉对方自己的位置和航向。飞机越多,通信关系越复杂,任何一架飞机加入或离开,所有其他飞机都要重新建立联系——这种"多对多"的直接通信几乎无法维护。
航空业给出的答案就是塔台:所有飞机只和塔台通信,塔台统一调度、协调各飞机之间的飞行路线。飞机之间互不直接联系,但整个机场依然秩序井然。
中介者模式(Mediator Pattern)正是这种思想的软件实现:用一个中介对象封装一系列对象之间的交互,让对象之间不再直接引用彼此,而是通过中介者间接通信,从而大大降低对象之间的耦合。
定义
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.
用一个中介对象来封装一系列的 对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
把"多对多"的交互关系变成"一对多":每个对象只认识中介者,中介者认识所有对象。
结构
让我们从一个问题开始
假设我们要开发一个多人聊天室。最直接的实现是:每个用户都持有其他所有用户的引用,发消息时直接调用对方的接收方法:
public class User {
private String name;
private List<User> friends = new ArrayList<>();
public void send(String message) {
// 直接给所有朋友发消息
for (User friend : friends) {
friend.receive(message);
}
}
public void receive(String message) {
System.out.println(name + " 收到消息:" + message);
}
}
问题显而易见:
- 每个用户都要维护一份"朋友列表",新增一个用户时,所有用户都要更新自己的列表;
- 用户之间显式相互引用,耦合极强,任何一方的变化都可能波及其他用户;
- 如果聊天室需要新增功能(比如"禁言""群发""消息记录"),就要修改每个用户类。
中介者模式的结构
引入一个聊天室(中介者),用户之间不再直接通信:
各个角色的职责如下:
- Mediator(中介者):定义同事对象之间通信的接口,对应图中的
Mediator。 - ConcreteMediator(具体中介者):实现中介者接口,协调各个同事对象之间的关系,对应图中的
ChatRoom。它需要知道所有同事对象,以便转发消息。 - Colleague(同事):定义同事对象的接口,每个同事只知道自己的中介者,不知道其他同事的存在。
- ConcreteColleague(具体同事):实现同事接口,通过中介者与其他同事通信,对应图中的
User。
关键点:同事对象只依赖中介者,同事之间互不引用。原来的"多对多"关系被简化成"一对多"。