如果你曾经把 iOS App 稍微做大一些,应该遇到过这样的时刻。
一个页面有五六个 View:A 一变,B 也要变;B 变了,C 还得跟着调整。
不知不觉间,View 之间开始相互直接引用,像线团一样纠缠在一起。
这时候,Mediator 模式正好可以帮你理清关系。
Swift Mediator 模式让对象不再直接相互引用,而只与 Mediator 通信,从而降低耦合度。
本文将结合示例代码,讲解 Mediator 模式是什么、何时适合使用,以及如何用 Swift 实现。
什么是 Mediator 模式?
用一句话来说:
在需要通信的对象之间放置一个中介者,让所有对话都经过这个中介者。
可以把它比作机场塔台。
如果飞机之间通过无线电说“你先降落”“我先来”,就会发生重大事故。
所以每架飞机只与塔台沟通,由塔台安排顺序。
这里的飞机就是代码中的对象,而塔台就是 Mediator。
Mediator 模式要解决的核心问题是:
- 移除直接引用:对象 A 不再需要逐个了解 B、C、D
- 集中通信逻辑:复杂的交互规则集中到一个 Mediator 中
- 提升复用性:对象彼此独立,方便在其他页面复用
什么时候应该使用 Mediator 模式?
它并不适合所有情况。我看到以下信号时,会考虑引入它。
当对象彼此了解过多时,也就是打开一个类后,会接连出现对其他对象的引用。
另一种情况是,修改一段逻辑却必须同时调整多个相关对象。
典型使用场景如下:
| 场景 | 示例 |
|---|---|
| 复杂页面 UI | 多个按钮和标签根据表单输入值连锁反应 |
| 组件协调 | 在聊天室参与者之间转发消息 |
| 工作流控制 | 管理支付各阶段的 View 状态 |
反过来,如果只有两三个对象且关系简单,最好不要勉强使用。
否则中介者可能无谓地膨胀,变成“God Object”。
如何实现 Swift Mediator 模式?
以聊天室为例。参与者不直接互发消息,而是通过聊天室(Mediator)进行通信。
首先定义 Mediator 必须遵守的协议和参与者。
// Mediator 必须遵守的规则
protocol ChatMediator {
func send(_ message: String, from user: User)
func add(_ user: User)
}
关键在于,参与者只了解 Mediator,不直接引用其他参与者。
class User {
let name: String
weak var mediator: ChatMediator? // 避免循环引用
init(name: String) { self.name = name }
func send(_ text: String) {
mediator?.send(text, from: self) // 委托给 Mediator
}
func receive(_ text: String) {
print("\(name) 收到: \(text)")
}
}
最后由 Mediator 负责实际的传递规则:只向发送者以外的其他人广播消息。
class ChatRoom: ChatMediator {
private var users: [User] = []
func add(_ user: User) { users.append(user); user.mediator = self }
func send(_ message: String, from user: User) {
users.filter { $0 !== user }
.forEach { $0.receive("[\(user.name)] \(message)") }
}
}
无论用户增加多少,都不需要修改 User 类,因为只有 ChatRoom 了解传递规则。
Mediator vs Observer:有什么区别?
很多人确实容易混淆这两者。
简单总结一下区别:
| 分类 | Mediator | Observer |
|---|---|---|
| 方向 | 集中管理多对多通信 | 一对多通知(发布-订阅) |
| 关系 | 对象通过 Mediator 进行交互 | 被观察者通知观察者 |
| 重点 | 复杂的相互“协调” | 状态变化的“传播” |
简单来说,Observer 是单方面通知“我变了!”的一方。
Mediator 则会判断“这种情况下谁应该做什么?”,并协调对象之间的关系。
在 Swift 中,Combine 和 NotificationCenter 更接近 Observer 类型,而 Mediator 通常需要自行实现。
常见问题(Q&A)
问:如果 Mediator 变得太大怎么办?
由于逻辑集中在这里,Mediator 很容易变得臃肿。可以按功能拆分成多个 Mediator,或将内部逻辑分离到独立的辅助对象中。
问:一定要使用 weak 吗?
是的。如果参与者和 Mediator 彼此强引用,就会因循环引用产生内存泄漏。请像示例一样将一方设为 weak。
问:SwiftUI 中也能使用吗?
可以。ViewModel 往往实际上扮演着 View 之间的 Mediator 角色,可以通过一个 ViewModel 自然地协调多个 View 的状态。
如果对象彼此纠缠,已经让你不敢修改代码,不妨试试加入 Mediator 模式。
只需建立一个 Mediator,就能让每个对象轻量许多,之后添加功能也更安心。
推荐你把今天的示例代码原样应用到一个小项目中。亲自写一遍,很快就能掌握。😊

