中介者模式和观察者模式有什么区别?
简化版
观察者模式强调“一对多通知”,被观察者状态变化后通知观察者;中介者模式强调“多对象协作协调”,多个对象把交互交给中介者统一处理。观察者偏通知机制,中介者偏协作规则中心。
详细版
两者都能降低对象直接耦合,但意图不同:
| 对比点 | 中介者模式 | 观察者模式 |
|---|---|---|
| 核心意图 | 协调多个对象之间的复杂交互 | 一个对象变化后通知多个依赖者 |
| 关系结构 | 多个同事对象通过中介者交互 | Subject 维护 Observer 列表 |
| 关注重点 | 谁影响谁、怎么协调 | 谁订阅谁、变化后通知 |
| 控制逻辑 | 通常集中在中介者 | 通常分散在各观察者 |
| 典型场景 | UI 组件联动、聊天室、塔台调度 | 事件监听、发布订阅、状态变更通知 |
面试里可以说:如果重点是“变化通知”,更像观察者;如果重点是“多个对象之间复杂协调”,更像中介者。
完整版教学
一、两个模式为什么容易混
它们都能避免对象之间直接强依赖。
比如按钮点击后更新输入框、列表、提示区域。你可以说:
- 按钮事件通知多个监听器,这是观察者;
- 多个组件由弹窗中介者统一协调,这是中介者。
看起来都能实现,所以容易混。
区别不在代码是否有“通知”,而在设计意图。
二、观察者模式的重点是状态变化通知
观察者模式通常有一个 Subject:
interface Observer {
void update(String event);
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void notifyObservers(String event) {
for (Observer observer : observers) {
observer.update(event);
}
}
}
Subject 的核心职责是维护观察者列表并通知。
它不一定知道每个观察者收到通知后要做什么。观察者自己决定响应逻辑。
所以观察者模式更像“广播通知”。
三、中介者模式的重点是协作规则
中介者模式中,协调逻辑通常在中介者里。
class LoginDialogMediator {
private TextBox username;
private TextBox password;
private Button loginButton;
public void changed() {
loginButton.setEnabled(username.hasText() && password.hasText());
}
}
这里重点不是简单通知,而是中介者明确知道:
- 用户名输入框变化会影响登录按钮;
- 密码输入框变化也会影响登录按钮;
- 启用按钮的规则是什么。
所以中介者更像“协调中心”。
四、从依赖关系看区别
观察者模式里:
Subject -> Observer[]
被观察者维护观察者列表,通知它们。
中介者模式里:
ColleagueA -> Mediator -> ColleagueB / ColleagueC
多个同事对象通过中介者互相影响。
观察者可以是单向通知,中介者常常是多方交互。
五、真实项目中可以组合使用
两者并不冲突。
比如一个前端页面:
- UI 组件触发事件,这部分可以是观察者;
- 页面协调器根据事件更新多个组件,这部分是中介者思想。
再比如事件总线:
- 事件总线提供发布订阅能力,像观察者;
- 如果事件总线里写了大量业务路由和协调规则,又带有中介者味道。
面试时不要死抠分类,可以强调主意图。
六、面试回答技巧
可以这样回答:
观察者模式解决的是对象状态变化后的订阅通知问题,中介者模式解决的是多个对象之间复杂交互的集中协调问题。观察者更偏事件通知机制,中介者更偏协作规则编排。
然后补一句:
如果只是 A 变化后通知 B、C,像观察者;如果 A、B、C、D 之间互相影响,需要一个中心统一判断和调度,像中介者。
七、常见误区与追问
中介者与观察者都能减少直接引用,但通信语义不同。观察者中1个 Subject 通知 N 个 Observer,重点是一对多状态传播;中介者接收某个同事事件后,可能选择另外2个同事执行不同动作,重点是多对象协调。事件总线可作为中介者的通信手段,但不自动产生协调规则。
| 检查维度 | 判定依据 |
|---|---|
| 观察者 | 主题变化后广播给订阅者 |
| 中介者 | 中心根据事件决定对象间协作 |
Observer: S -> O1..N;Mediator: C1 -> M -> C2/C3
记忆钩子:观察者负责“通知大家”,中介者负责“安排大家”。
- 误区:两种模式完全互斥。 中介者内部可以使用观察者分发同事事件。
- 追问:谁知道参与者? 经典中介者通常知道需要协调的同事,Subject 只维护订阅抽象。
- 误区:使用事件总线就是观察者而不是中介者。 要看上层意图;事件传输和协调规则可以同时存在。
- 追问:哪种更容易形成广播风暴? 观察者或事件总线订阅过多时更明显,但中介者循环触发也有风险。
- 追问:面试怎么判断? 看核心问题是一对多通知,还是多对象网状交互的集中协调。
八、加强记忆
观察者模式记“一个变化,多个订阅者收到通知”;中介者模式记“多个对象,复杂关系交给中心协调”。两者都能解耦,但观察者偏通知,中介者偏协调。判断时优先看意图,不要只看有没有事件或回调。