中介者模式:让对象之间的“社交”变得优雅
说实话,我刚开始接触设计模式那会儿,对中介者模式是有点不屑的。心想:不就是加个中间层吗?有什么了不起的。直到我在一个大型聊天系统项目中栽了跟头——那时候每个用户对象都要知道其他所有用户对象的存在,代码耦合得像一团乱麻。嗯,从那以后,我才真正理解了中介者模式的妙处。
什么是中介者模式?
说白了,中介者模式就是给一群对象找个“管家”。这些对象不再直接互相喊话,而是通过这个管家来传递消息。你想想看,如果办公室里每个人都直接找其他人沟通,那得多乱?有个前台或者秘书统一协调,事情就清爽多了。
核心定义:用一个中介对象来封装一系列对象的交互,使各对象不需要显式地相互引用。
这个模式解决的核心问题就是:对象之间的多对多关系。没有中介者的时候,N个对象互相通信,需要维护N*(N-1)条连接。有了中介者,只需要N条连接——每个对象只跟中介者说话。
模式结构
中介者模式包含以下几个关键角色:
- Mediator(中介者接口):定义通信接口,声明同事对象之间如何交互
- ConcreteMediator(具体中介者):实现中介者接口,协调各个同事对象的交互逻辑
- Colleague(同事类):每个同事对象都持有中介者的引用,需要通信时调用中介者
这里我画了一张图,帮你理清它们之间的关系:
一个真实的代码例子
我记得有一次做智能家居控制系统,需要协调灯光、空调、窗帘、安防等多个设备。如果每个设备都直接控制其他设备,那代码简直没法维护。用中介者模式就清爽多了。
来看一个简化版的聊天室例子:
// 中介者接口
public interface ChatMediator {
void sendMessage(String message, User user);
void addUser(User user);
}
// 具体中介者 - 聊天室
public class ChatRoom implements ChatMediator {
private List<User> users = new ArrayList<>();
@Override
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String message, User sender) {
for (User user : users) {
// 消息不发给发送者自己
if (user != sender) {
user.receive(message);
}
}
}
}
// 同事类 - 用户
public abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void send(String message);
public abstract void receive(String message);
}
// 具体同事
public class ChatUser extends User {
public ChatUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void send(String message) {
System.out.println(name + " 发送: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receive(String message) {
System.out.println(name + " 收到: " + message);
}
}
// 使用示例
public class Demo {
public static void main(String[] args) {
ChatMediator chatRoom = new ChatRoom();
User alice = new ChatUser(chatRoom, "Alice");
User bob = new ChatUser(chatRoom, "Bob");
User charlie = new ChatUser(chatRoom, "Charlie");
chatRoom.addUser(alice);
chatRoom.addUser(bob);
chatRoom.addUser(charlie);
alice.send("大家好!");
// 输出:
// Alice 发送: 大家好!
// Bob 收到: 大家好!
// Charlie 收到: 大家好!
}
}
我的经验之谈:在实际项目中,中介者模式特别适合用在UI组件协调、消息中间件、工作流引擎这些场景。我做过一个表单验证系统,十几个输入框之间互相影响,用中介者模式后,每个输入框只跟验证管理器通信,代码量减少了40%。
什么时候该用中介者模式?
我个人习惯用下面这个检查清单来判断:
| 场景特征 | 是否适合中介者模式 |
|---|---|
| 一组对象以复杂但定义良好的方式通信 | ✅ 非常适合 |
| 对象之间的依赖关系混乱,难以复用 | ✅ 非常适合 |
| 想要通过一个中间层来集中控制交互逻辑 | ✅ 非常适合 |
| 对象数量少且通信简单 | ❌ 过度设计 |
| 需要高性能、低延迟的通信 | ⚠️ 谨慎使用(中介者可能成为瓶颈) |
避坑指南:我曾经在一个实时交易系统中滥用中介者模式,结果中介者对象变得超级臃肿,成了上帝对象。记住:中介者不是万能的,当交互逻辑过于复杂时,考虑把中介者拆分成多个更专注的协调器。
中介者模式的优缺点
任何模式都有两面性,中介者模式也不例外:
- 优点:
- 降低了同事类之间的耦合度,每个类只依赖中介者
- 将多对多的交互简化为一对多
- 交互逻辑集中管理,便于维护和修改
- 缺点:
- 中介者可能变得过于复杂,成为单点故障
- 如果同事类之间交互逻辑频繁变化,中介者也需要频繁修改
- 增加了系统的间接性,调试时可能需要多跳一层
与观察者模式的对比
很多初学者会把中介者模式和观察者模式搞混。我简单说说区别:
- 观察者模式:一对多关系,一个主题变化,多个观察者收到通知。通信是单向的。
- 中介者模式:多对多关系,所有同事通过中介者互相通信。通信是双向的。
说白了,观察者模式适合「广播通知」的场景,中介者模式适合「多方协调」的场景。你想想看,天气预报App用观察者模式就挺好,但一个多人视频会议系统,用中介者模式更合适。
小结
中介者模式的核心思想就是:不要让对象之间直接谈恋爱,给它们找个媒人。这个媒人负责牵线搭桥,让每个对象只专注于自己的事情。我在多个项目中实践下来,这个模式特别适合那些「对象之间关系复杂、但交互规则相对稳定」的系统。
嗯,最后提醒一句:别为了用模式而用模式。如果你的系统只有两三个对象在通信,直接调用就完事了,没必要硬套中介者。设计模式是工具,不是教条。
公众号:蓝海资料掘金营,微信deep3321