观察者模式:
定义了对象之间的一对多依赖,这样一来,当一个对象改变的时候,它的所有依赖者就会自动更新。 // 而这个对象 就称之为 主题,这些依赖者就称之为 观察者
该模式的组成部分:
- 主题 部分: 主题 的协议, 各个负责 具体实现 的主题;
- 观察者 部分: 观察者协议, 各个观察者的具体实现类;
OO原则:
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合而设计
UML 类图:
代码具体实现:
1、主题部分:
// 主题 协议 protocol WeatherDataSubject { // 提供 接口 给 观察者,以便他们 进行订阅、退订 和 获取数据 func registerObserver(observer: WeatherDataObserverInterface) func removeObserver(observer: WeatherDataObserverInterface) // 获取数据, 将各个数据分开,以便不同的 观察者 获取自己所需要的不同数据 func gainTemperature() -> Float func gainHumidity() -> Float func gainPressure() -> Float } // 一个 具体实现 的主题 class WeatherData: NSObject, WeatherDataSubject { var observers: NSMutableArray = NSMutableArray() private var temperature: Float = 0.0 private var humidity: Float = 0.0 private var pressure: Float = 0.0 // 用来表示 主题进行了数据更新 var changeState: Bool = true // 观察者 注册/订阅 func registerObserver(observer: WeatherDataObserverInterface) { observers.addObject(observer as! AnyObject) } // 观察者 退订 func removeObserver(observer: WeatherDataObserverInterface) { observers.removeObject(observer as! AnyObject) } // 当主题进行了数据更新, 就将 更新消息 发送给各订阅者(通过 调用观察者协议的 获取更新数据 方法) func notificationObservers() { if changeState { for observer in observers { (observer as! WeatherDataObserverInterface).updateWeather() } changeState = false } } // 提供数据接口 给观察者 func gainHumidity() -> Float { return self.humidity } func gainPressure() -> Float { return self.pressure } func gainTemperature() -> Float { return self.temperature } // 各个主题 自带的更新数据 方法 func changeWeatherData(t: Float, h: Float, p: Float) { self.temperature = t self.pressure = p self.humidity = h changeState = true self.notificationObservers() } }
2、 观察者部分:
// 观察者协议类 protocol WeatherDataObserverInterface { // 本协议比较简单, 只有一个获取 主题更新消息 的方法/接口 和 退订接口 func updateWeather() func removeSubject() } // 一个具体的观察者类 class CurrentConditionsDisplay:NSObject, WeatherDataObserverInterface { private var temperature: Float = 0.0 private var humidity: Float = 0.0 // 一个 主题协议对象 var weatherDataSubject: WeatherDataSubject? // 在生成 观察者对象的时候,需要传入一个主题,以便该观察者在生成的时候就去注册该主题 init(weatherData: WeatherData) { super.init() weatherDataSubject = weatherData weatherDataSubject?.registerObserver(self) // 注册 } // 接受 主题更新 的消息,接受到后,就去 所注册的主题处获取所需的数据 func updateWeather() { self.temperature = weatherDataSubject!.gainTemperature() self.humidity = weatherDataSubject!.gainHumidity() self.display() } // 展示数据 func display() { println("I'm Current Conditions Panel Display") println("current temperature is (self.temperature). And humidity is (self.humidity)") println() } // 实现 退订 func removeSubject() { weatherDataSubject?.removeObserver(self) } }
3、具体实现(测试):
// 生成一个具体 的主题 var weatherData = WeatherData() // 生成一个具体 的观察者 var curentConditon: CurrentConditionsDisplay = CurrentConditionsDisplay(weatherData: weatherData) // 主题 更新数据 weatherData.changeWeatherData(1, h: 1, p: 1) // 观察者退订主题 curentConditon.removeSubject() // 主题 再次更新数据 weatherData.changeWeatherData(2, h: 2, p: 2)
4、测试结果:
只输出了一次结果,即:主题第一个更新的结果,因为主题进行第二次更新的时候,观察者已经退订了,所以不能接受到主题更新后的数据,也就不能输出。
I'm Current Conditions Panel Display current temperature is 1.0. And humidity is 1.0