1. 何为观察者模式
观察者模式也叫做发布-订阅模式。如它的别名暗示的那样,它很像杂志的订阅。当从杂志发行商订阅杂志的时候,读者把名字和邮寄地址提供给发行商,这样新的一期就能送到读者手上了。发行商保证把正确的杂志发送到正确的地址,一般来说,读者不会收到他没有订阅的杂志。这正是订阅者模式的工作方式。
观察者通过通知器(发行商)把自己注册到(订阅)特定的通知(杂志)。当有通知的时候,观察者只从通知器得到它订阅的通知。
Observer从Subject订阅通知,ConcreteObserver实现抽象Observer并重载其update犯法。一旦Subject的实例需要通知Observer任何新的变更,Subject会发送update消息来通知存储在内部列表中所有注册的Observer。在ConcreteObserver的update方法的实际实现中,Subject的内部状态可被取得并在以后进行处理。
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都的到通知并被自动更新。
在观察者模式里,一个对象在状态变化的时候会通知另一个对象。参与者并不需要知道其他对象的具体是干什么的 - 这是一种降低耦合度的设计。这个设计模式常用于在某个属性改变的时候通知关注该属性的对象。
常见的使用方法是观察者注册监听,然后再状态改变的时候,所有观察者们都会收到通知。
Cocoa 使用两种方式实现了观察者模式: Notification 和 Key-Value Observing (KVO)
2. 通知-Notification 和 键值观察-KVO
这里所讲的通知是基于订阅-发布模式的,即一个对象(发布者)向其他对象(订阅者)发送消息。发布者永远不需要知道订阅者的任何数据。
Apple对于通知的使用很频繁,比如当键盘弹出或者收起的时候,系统会分别发送UIKeyboardWillShowNotification/UIKeyboardWillHideNotification 的通知。当你的应用切到后台的时候,又会发送 UIApplicationDidEnterBackgroundNotification 的通知。
- 注意:打开 UIApplication.swift 文件,在文件结尾你会看到二十多种系统发送的通知。
在 KVO 里,对象可以注册监听任何属性的变化,不管它是否持有。如果感兴趣的话,可以读一读苹果 KVO 编程指南。
3. 代码实现
import Foundation
class Observer {
func updateData(data: String) {}
}
class CourseObserver: Observer {
override func updateData(data: String) {
print("课程更新了---\(data)")
}
}
class StudyObserver: Observer {
override func updateData(data: String) {
print("学习更新了---\(data)")
}
}
class ObserverCenter {
var observerMap: [String: Observer] = [:]
func addObserver(observerName: String, observer: Observer) {
observerMap[observerName] = observer
}
func deleteObserver(observerName: String) {
observerMap.removeValue(forKey: observerName)
}
func notifyObserver(data: String) {
for (_, value) in observerMap {
let observer: Observer = value
observer.updateData(data: data)
}
}
}
let observerCenter: ObserverCenter = ObserverCenter()
let courseObserver: CourseObserver = CourseObserver()
observerCenter.addObserver(observerName: "Course", observer: courseObserver)
let studentObserver: StudyObserver = StudyObserver()
observerCenter.addObserver(observerName: "Student", observer: studentObserver)
observerCenter.notifyObserver(data: "FlyElephant")