进行 iOS 开发时,你会不断遇到 Delegate 模式。
每次使用 UITableView、UITextField 都要添加 delegate,你可能都想过:“为什么是 delegate?直接用闭包或通知不行吗?”
尤其学完 Observer 模式后,反而更容易混淆。两者都是“发生事情时发出通知”的结构,到底有什么不同?
先说结论。
Delegate 是一种 1:1 通信:一个对象把事情委托给唯一的一个对象,“这件事交给你了”。
Observer 是一种 1:N 广播:多个订阅者同时订阅同一个事件。
理解这一句话,你就已经掌握了一半。今天我们结合代码彻底梳理两者的区别。
什么是 Delegate 模式?
Delegate 的意思就是“委托”。
把自己不方便处理的事情交给一个值得信赖的对象:“你替我决定吧。”
可以用生活中的例子来理解。
我想预订餐厅,但懒得亲自打电话,于是请一位助理帮忙:“替我预订一下。”
这里的助理就是 Delegate。委托方一个人,受托方也一个人,正好是 1:1。
在 Swift 中,我们通过协议约定这种关系。
// 在协议中定义要委托的工作
protocol OrderDelegate: AnyObject {
func didFinishOrder(_ menu: String)
}
class Restaurant {
weak var delegate: OrderDelegate? // 只指定一个对象
func order(_ menu: String) {
delegate?.didFinishOrder(menu) // 只通知这一个对象
}
}
这里要注意,delegate不是数组,而是一个属性。
既然只委托给一个对象,自然只保存一个。这就是 Delegate 是 1:1 的原因。
而且还有weak。相互强引用会形成 retain cycle,导致内存泄漏,因此 Delegate 通常使用 weak 引用。
它和 Observer 模式有什么不同?
Observer 就是“观察者”。
事件发生时,通知会一次性发送给正在观察它的多个对象。
继续沿用刚才的助理例子。
这次,我把餐厅开业的消息广播给整个街区:“今晚开业!”
听众可能有十个人,也可能有一百个人。我不关心谁在听,只负责把消息发出去。
这就是 1:N 广播,也就是 Observer 模式。
在 iOS 中,NotificationCenter就是典型例子。
// 事件发生 → 广播给所有订阅者
NotificationCenter.default.post(name: .storeOpen, object: nil)
// 感兴趣的对象分别订阅
NotificationCenter.default.addObserver(
self, selector: #selector(handleOpen),
name: .storeOpen, object: nil)
发送方不知道接收者是谁,只是加上名称后发送出去。
接收方也由多个对象分别订阅。
彼此无需了解,因此耦合度较低;但缺点是很难追踪当前是谁在接收通知。
Delegate 与 Observer 一目了然的对比
只用文字说明容易混淆,所以我整理成了表格。
| 分类 | Delegate | Observer |
|---|---|---|
| 通信方式 | 1:1(委托给一个对象) | 1:N(广播给多个对象) |
| 是否了解对方 | 彼此明确了解 | 彼此无需了解 |
| 典型示例 | UITableViewDelegate | NotificationCenter |
| 响应(返回值) | 容易接收 | 较难接收 |
| 耦合度 | 相对较高 | 低 |
| 跟踪/调试 | 容易 | 比较困难 |
关键在于:“是否需要得到响应?”
使用 Delegate 时,询问“这个单元格应该多高?”对方会返回一个值。这是双向交流的结构。
Observer 只是发送后结束。发送方不关心谁会如何响应。
那么什么时候该用哪个?
这是我在实际项目中使用后总结出的判断标准。
使用 Delegate 的场景
- 只需要与一个对象通信时
- 需要从对方获取返回值时(例如单元格数量、高度)
- 屏幕跳转等顺序和流程明确时
使用 Observer 的场景
- 一个事件需要多个页面同时响应时
- 登录状态变化、切换深色模式等全局事件
- 发送方和接收方无需互相了解时
例如登录成功后,首页、个人中心和顶部横幅都要同时变化时,Delegate 就不够用了。
因为只能委托给一个对象,要连接三个地方会让代码变得杂乱。
这时用 Observer 广播一次“登录成功了!”会清爽得多。
相反,“点击了输入框中的确认按钮”这种 1:1 场景,Delegate 或闭包才是正确选择。
总结
即使两者看起来相似,只要想想“要通知多少人”,选择就会变得简单。
一个人用 Delegate,多个人用 Observer。记住这一条标准就够了。
下次写代码时,试着应用今天学到的内容吧。当只停留在脑中的知识真正变成手上的经验,模式就会容易很多。加油!

