中介者模式:让对象间的沟通不再混乱
说实话,我刚开始做架构设计那几年,最头疼的就是对象之间的通信问题。你想想看,一个系统里十几个类互相调用,A调B,B调C,C又调A……代码写到最后,自己都理不清谁依赖谁。后来我接触到了中介者模式,才明白——原来很多混乱,都是因为缺少一个「中间人」。
中介者模式,说白了就是给一群对象找个「管家」。所有对象不再直接互相通信,而是通过这个管家来协调。这样,对象之间就解耦了,各自只关心自己的事。
中介者模式的结构
这个模式的结构其实很清晰,我画了张图帮你理解:
这个模式里有几个关键角色:
- 中介者接口:定义了通信的方法,比如 notify、send 之类的。
- 具体中介者:实现协调逻辑,知道每个同事类该做什么。
- 同事类:就是那些原本要互相调用的对象,现在只依赖中介者。
我在项目中遇到过这样一个场景:一个聊天室系统,用户、群组、消息管理三个模块互相调用。用户发消息要通知群组,群组要更新消息列表,消息管理要记录日志……代码耦合得一塌糊涂。后来我用中介者模式,引入了一个 ChatMediator,所有模块只跟它通信,瞬间清爽了。
中介者模式 vs 观察者模式
这两个模式经常被拿来比较,我刚开始学的时候也容易搞混。其实它们的核心区别在于——通信的方向和目的不同。
| 对比维度 | 中介者模式 | 观察者模式 |
|---|---|---|
| 通信方向 | 多对多 → 集中到中介者 | 一对多(一个主题,多个观察者) |
| 目的 | 解耦多个对象之间的交互 | 状态变化时通知依赖方 |
| 控制权 | 中介者主动协调 | 观察者被动接收通知 |
| 典型场景 | 对话框组件、聊天室、工作流 | 事件监听、数据绑定、消息队列 |
举个例子你就明白了。观察者模式就像你订阅了一个公众号——公众号发文章,你被动收到通知。而中介者模式更像一个会议室——所有人都在会议室里说话,会议室(中介者)负责把话传给该听的人。
中介者模式在 MVC 中的 Controller 角色
说到中介者模式,就不得不提 MVC 架构。你想想看,MVC 里的 Controller 在干什么?
- 用户点击按钮 → View 通知 Controller
- Controller 更新 Model
- Model 变化 → Controller 通知 View 刷新
这不就是中介者吗?View 和 Model 不直接通信,全由 Controller 来协调。我习惯把 Controller 看作「胶水代码」——它不负责业务逻辑,只负责把 View 的事件转成 Model 的操作,再把 Model 的变化转成 View 的更新。
来看一段简单的代码示例:
// 中介者 —— Controller
class UserController {
constructor(userModel, userView) {
this.model = userModel;
this.view = userView;
// View 通知 Controller
this.view.onSaveButtonClick((data) => {
this.handleSaveUser(data);
});
}
handleSaveUser(data) {
// Controller 协调 Model
this.model.save(data);
// Controller 协调 View
this.view.showSuccessMessage();
this.view.refreshList(this.model.getAll());
}
}
// View 和 Model 之间没有直接依赖
class UserView {
onSaveButtonClick(callback) {
// 绑定按钮点击事件
}
}
class UserModel {
save(data) { /* 保存逻辑 */ }
getAll() { /* 查询逻辑 */ }
}
不过这里有个坑——Controller 如果太「厚」,就会变成上帝对象。我曾经接手过一个老项目,Controller 里既有数据校验、又有权限判断、还有日志记录……改一个功能要动十几个方法。后来我重构时,把校验逻辑放到了 Model 层,权限判断放到了中间件,Controller 只保留路由和协调,代码量直接砍了一半。
总结一下中介者模式的核心价值:它把「网状结构」变成了「星型结构」。每个对象只跟中介者打交道,降低了耦合度,也让系统的扩展性更好。你想想看,如果以后要加一个新同事类,只需要让它跟中介者通信就行,其他类完全不用改——这就是开闭原则的体现。
我个人习惯在系统设计初期,先画出对象之间的通信图。如果发现连线太多、关系复杂,就会考虑引入中介者模式。这个习惯帮我避免了很多后期重构的麻烦。
公众号:蓝海资料掘金营,微信deep3321