iOS Swift 设计模式|观察者模式详解(原理+实战场景+代码示例)
📖 前言
在 iOS 中大型项目开发中,观察者模式(Observer Pattern)是最常用的行为型设计模式。它主要用于对象之间消息通知、状态监听、事件同步,实现代码解耦。
iOS 开发中随处可见观察者思想:NotificationCenter、KVO、Combine、RxSwift 全部底层基于观察者模式。
本文详细讲解:观察者模式概念、核心原理、两种实现方式、项目真实使用场景、完整可复用代码、优缺点以及开发规范,适合面试背诵、项目开发、博文沉淀。
一、观察者模式核心概念
1.1 什么是观察者模式?
观察者模式属于行为型设计模式,定义了一种一对多的依赖关系:
当一个对象(被观察者)状态发生改变时,所有依赖它的对象(观察者)都会自动收到通知并更新。
1.2 核心角色
-
被观察者(Subject):维护观察者数组、提供添加/移除/通知方法。
-
观察者(Observer):接收回调、执行更新逻辑。
1.3 核心思想
-
松耦合:被观察者、观察者互相不硬依赖
-
一对多广播:一处改变,多处响应
-
事件驱动:无需轮询,被动接收通知
二、iOS 中常见观察者实现方式
Swift 项目开发中,观察者模式分为两大类:
2.1 系统原生实现
-
NotificationCenter:全局通知,跨页面、跨模块通信
-
KVO:监听属性变化
-
Combine:Swift 原生响应式框架(SwiftUI 主流)
2.2 第三方/手写实现
-
RxSwift/RxCocoa:企业级主流响应式
-
手写原生观察者:轻量自定义监听、无依赖
三、手写最简观察者模式(底层原理版)
为了彻底理解底层,下面手写一套纯原生、无任何依赖观察者模型,看懂等于吃透原理。
3.1 步骤1:定义观察者协议
import Foundation
// 观察者协议
protocol Observer: AnyObject {
func update(message: String)
}
3.2 步骤2:创建被观察者
// 被观察者
class Subject {
// 持有所有观察者(弱引用防止内存泄漏)
private var observers: [Observer] = []
// 添加观察者
func addObserver(_ observer: Observer) {
observers.append(observer)
}
// 移除观察者
func removeObserver(_ observer: Observer) {
observers.removeAll { $0 === observer }
}
// 广播通知
func notify(message: String) {
observers.forEach {
$0.update(message: message)
}
}
}
3.3 步骤3:创建具体观察者
// 观察者A
class ObserverA: Observer {
func update(message: String) {
print("观察者A收到消息:\(message)")
}
}
// 观察者B
class ObserverB: Observer {
func update(message: String) {
print("观察者B收到消息:\(message)")
}
}
3.4 使用示例
// 创建被观察者
let subject = Subject()
// 创建观察者
let observerA = ObserverA()
let observerB = ObserverB()
// 注册监听
subject.addObserver(observerA)
subject.addObserver(observerB)
// 发出广播(所有观察者自动回调)
subject.notify(message: "用户登录成功")
3.5 输出结果
观察者A收到消息:用户登录成功
观察者B收到消息:用户登录成功
四、项目高频实战写法(NotificationCenter)
开发中最常用、最简单的观察者就是系统通知,适合跨页面、无耦合通信。
4.1 发送通知
// 任意位置发送
NotificationCenter.default.post(name: NSNotification.Name("UserLoginSuccess"), object: nil)
4.2 监听通知
// 在需要监听的页面接收
NotificationCenter.default.addObserver(self, selector: #selector(loginEvent), name: NSNotification.Name("UserLoginSuccess"), object: nil)
@objc func loginEvent() {
print("监听到用户登录,刷新个人中心")
}
4.3 移除监听(必须操作)
deinit {
NotificationCenter.default.removeObserver(self)
}
五、进阶:Combine 响应式观察者(SwiftUI 主流)
Swift 原生响应式框架,无第三方依赖,适合 MVVM、SwiftUI 数据流绑定。
import Combine
class UserViewModel {
// 被观察者:发布者
@Published var isLogin: Bool = false
}
// 监听
let vm = UserViewModel()
vm.$isLogin.sink { isLogin in
print("当前登录状态:\(isLogin)")
}
// 改变状态、自动触发监听
vm.isLogin = true
六、观察者模式 在 iOS 项目真实使用场景
以下为中大型Swift项目高频业务场景:
-
用户登录/退出登录全局监听
登录后刷新个人中心、购物车、权限、首页数据。 -
暗黑模式、语言切换
全局发送通知,所有页面自动刷新UI。 -
网络状态监听
有无网络、WiFi/流量切换,统一弹窗提示。 -
IM聊天消息推送
收到消息,聊天列表、红点、会话实时刷新。 -
订单状态变更
支付成功、发货、签收,多页面同步刷新状态。 -
埋点、全局事件统计
一处发送、多处统计上报,业务解耦。
七、观察者模式优缺点
7.1 优点
-
完全解耦:发布者、观察者互不依赖
-
一对多广播:一次通知,多处响应
-
动态注册:运行时随意添加、移除监听
-
遵循开闭原则:新增观察者无需修改原有代码
7.2 缺点
-
消息无序:无法控制接收顺序
-
内存泄漏风险:不及时移除监听会强引用残留
-
消息链路隐蔽:通知过多难以排查调用链路
八、开发注意事项(避坑⚠️)
-
必须移除监听:Notification、KVO 一定要在 dealloc 销毁,防止内存泄漏。
-
禁止滥用全局通知:大型项目通知过多,排查难度极高。
-
循环引用防范:自定义观察者一定要使用
weak弱引用存储观察者。 -
复杂业务优先 Combine/RxSwift:原生通知适合简单事件,复杂数据流使用响应式。
九、总结
-
观察者模式是一对多事件广播,核心是状态变动自动通知。
-
iOS 三大实现:手写观察者、Notification、Combine。
-
适合:登录状态、主题切换、订单、IM、网络状态等全局事件。
-
开发重点:解耦、弱引用、及时销毁监听。
更多推荐
所有评论(0)