软件设计

Mediator vs Observer vs Facade 完整对比:3 种对象通信模式

Mediator 在中心协调复杂的对象关系,Observer 将状态变化一对多地通知出去,Facade 则用简单入口封装复杂内部实现。本文通过 Swift 示例比较三种模式的差异和选择标准。

4 分钟阅读
Mediator vs Observer vs Facade 完整对比:3 种对象通信模式 封面图

对象越来越多时,代码总会在某个时刻变成一团乱麻。当一个页面中的视图控制器、网络、缓存和日志记录器开始互相直接调用时,改好一处往往又会弄坏另一处。

这时通常会考虑 Mediator、Observer 和 Facade。三者都被介绍为“整理对象通信”的方式,但它们实际解决的问题并不相同。

Mediator 将纠缠的关系集中控制,Observer 通过一对多通知处理状态变化,Facade 则用简单入口隐藏复杂内部实现。

记住这一句话,你就完成一半了。下面我们结合代码说明各自的使用时机和差异。


先用一句话总结三种模式

先把核心内容整理出来,方便混淆时回看。

  1. Mediator — 多个对象不直接互相引用,而是通过一个中介者进行通信
  2. Observer — 一个对象的状态发生变化时,自动通知多个订阅它的对象
  3. Facade — 在复杂子系统前提供一个简单接口,将其隐藏起来

虽然三者都在整理“通信”,但侧重点不同。

Mediator 减少关系复杂度,Observer 处理变化传播,Facade 降低使用复杂度


Mediator vs Observer,有什么区别?

这两个最容易混淆,因为它们都能避免对象之间直接调用。

区别在于关系的方向

Observer 的方向很明确。一个 Subject 发生变化后,更新会沿一个方向流向订阅者。比如聊天室收到新消息时,页面、通知徽章和声音各自做出响应。

Mediator 的方向则彼此交织。点击按钮会激活文本框,而文本框又会改变保存按钮的状态,如此循环。这种多对多关系由中介者代为协调。

// Observer:状态变化沿一个方向传播
protocol Observer: AnyObject { func update(_ count: Int) }

final class Cart {
    private var observers: [Observer] = []
    var items = 0 { didSet { observers.forEach { $0.update(items) } } }
    func subscribe(_ o: Observer) { observers.append(o) }
}

final class Badge: Observer {
    func update(_ count: Int) { print("购物车徽章: \(count)") }
}

let cart = Cart()
cart.subscribe(Badge())
cart.items = 3
// 输出:购物车徽章: 3

购物车发生变化后,徽章会自动跟着更新。Cart 不需要知道 Badge 是什么。

而 Mediator 会由中介者持有对象之间的规则。

// Mediator:由中介者管理纠缠的规则
final class FormMediator {
    var isAgreed = false
    func agreedChanged(_ value: Bool, submit: Button) {
        isAgreed = value
        submit.isEnabled = value   // 规则:同意后启用提交
    }
}

final class Button { var isEnabled = false }

let submit = Button()
let mediator = FormMediator()
mediator.agreedChanged(true, submit: submit)
print(submit.isEnabled)
// 输出: true

复选框和按钮不需要直接了解彼此,中介者会代为执行“同意后启用提交”的规则。

对比 Mediator 双向协调与 Observer 单向通知的示意图
左侧是纠缠关系的协调,右侧是单向通知,侧重点不同

Facade 的侧重点略有不同

Facade 与前两者的目的本身就不同。它不是协调通信,而是将复杂内部封装起来使其不可见的模式。

假设完成一笔订单需要依次调用支付、库存、配送和通知模块。调用方的代码很快就会变得混乱。

Facade 会将这些统一到一个入口之后。

final class OrderFacade {
    func placeOrder(_ id: String) {
        Payment().charge(id)
        Stock().reduce(id)
        Delivery().book(id)
        print("完成订单: \(id)")
    }
}

OrderFacade().placeOrder("A-1024")
// 输出:订单完成: A-1024

从外部只需调用一次placeOrder即可。内部有多少模块都不必关心。

关键就在这里。Facade 不是让对象彼此通信,而是简化调用方与复杂系统之间的关系。方向朝向内部。


一眼对比

下面整理了我在 2026 年实际工作中的分类方式。

分类 Mediator Observer Facade
解决的问题 纠缠的多对多关系 状态变化传播 隐藏复杂内部实现
关系方向 相互交织(中心协调) 一对多(单向) 调用方→系统
耦合度变化 降低对象之间的耦合 分离主体与订阅者 降低使用复杂度
典型示例 表单校验、聊天室协调 通知、数据绑定 支付与订单统一 API

通过表格可以明显看出,三者并不重叠。


何时使用,何时避免

模式被滥用后反而会带来问题。如果把所有纠缠的关系都交给 Mediator,中介者很容易变成 God object。

  • Mediator — 当 3~4 个或更多对象彼此直接引用,且规则相互纠缠时使用。如果规则很简单,就应避免使用,否则中介者会变得过于庞大。
  • Observer — 当多个位置都需要知道某一处的变化时使用。不要忘记取消订阅,否则可能造成内存泄漏。
  • Facade — 当你想隐藏复杂的调用流程时使用。在必须精细控制内部实现的地方,它反而会造成阻碍。

一句话总结:关系纠缠用 Mediator,需要通知变化用 Observer,想隐藏流程用 Facade

一张桌子上放着显示 Swift 代码的显示器,屏幕贴有写着 FACADE 的便利贴
归根结底,代码能变得多简洁,就是选择模式的标准

面试时可以这样回答

问:Mediator 和 Observer 有什么区别?

Observer 是一对多结构,Subject 的状态变化会沿一个方向传播给订阅者。Mediator 是多对多结构,由中介者在中心协调相互纠缠的对象之间的交互规则。方向性和关系复杂度是两者的核心区别。

问:Facade 也能降低耦合度,它和 Mediator 有什么区别?

Facade 在子系统前提供一个简单接口,降低调用方与系统之间的使用复杂度。而 Mediator 的目的是协调同级对象之间的相互通信。可以回答:“Facade 是单向简化,Mediator 是交互协调。”


与其死记三种模式,不如先问自己当前的代码属于“关系纠缠问题”“变化传播问题”,还是“流程复杂问题”。确定答案后,模式自然会随之而来。今天的重构就选一个试着应用吧。

延伸阅读