定义
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
观察者模式结构图
在观察者模式中有如下角色:
- Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
- ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
- Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
2.观察者模式简单实现
观察者模式这种发布-订阅的形式我们可以拿微信公众号来举例,假设微信用户就是观察者,微信公众号是被观察者,有多个的微信用户关注了程序猿这个公众号,当这个公众号更新时就会通知这些订阅的微信用户。好了我们来看看用代码如何实现:
2.1 抽象观察者(Observer)
里面定义了一个更新的方法:
protocol Observer {
var id : Int { get } // property to get an id
func update<T>(with newValue: T)
}
2.2 具体观察者(ConcrereObserver)
微信用户是观察者,里面实现了更新的方法:
class ConcreteObserver: Observer {
private var _id: Int = 0
var id: Int {
get {
return self._id
}
}
init(id: Int) {
self._id = id
}
func update<T>(with newValue: T) {
print("Whoaa, observer #\(self.id) update with new value : ", newValue)
}
}
2.3 抽象被观察者(Subject)
抽象主题,提供了attach、detach、notify三个方法:
protocol Subject {
func addObserver(observer: Observer)
func removeObserver(observer: Observer)
func notifyAllObservers<T>(with newValue: T)
}
2.4 具体被观察者(ConcreteSubject)
微信公众号是具体主题(具体被观察者),里面存储了订阅该公众号的微信用户,并实现了抽象主题中的方法:
class ConcreteSubject<T>: Subject {
// private var _value: T! = nil
// private var _observers: [Observer] = []
var _value: T! = nil
var _observers: [Observer] = []
var value : T {
get {
return self._value
}
set {
self._value = newValue
// self.notifyAllObservers(with: newValue)
}
}
var observers: [Observer] {
get {
return self._observers
}
set {
self._observers = newValue
}
}
func addObserver(observer: Observer) {
observers.append(observer)
}
func removeObserver(observer: Observer) {
observers = observers.filter({ $0.id != observer.id })
}
func notifyAllObservers<T>(with newValue: T) {
for observer in observers {
observer.update(with: newValue)
}
}
}
2.5 客户端调用
var obs1 = ConcreteObserver(id: 1)
var obs2 = ConcreteObserver(id: 2)
var subject = ConcreteSubject<String>()
subject.addObserver(observer: obs1)
subject.addObserver(observer: obs2)
subject.value = "Surprise! New Feeds update."
subject.notifyAllObservers(with: subject.value)
subject.removeObserver(observer: obs1)
subject.value = "Obs1 removed, yey"
subject.notifyAllObservers(with: subject.value)
结果
Whoaa, observer #1 update with new value : Surprise! New Feeds update.
Whoaa, observer #2 update with new value : Surprise! New Feeds update.
Whoaa, observer #2 update with new value : Obs1 removed, yey
代码下载
https://gist.github.com/zgpeace/4b83c0efef771770169654f051401bea
参考
https://medium.com/99ridho/swift-design-pattern-observer-pattern-fc009b783d19
https://medium.com/swift-coding/the-observer-pattern-in-swift-97a0e6fafa58
http://liuwangshu.cn/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/