设计模式学习

观察者模式:

    定义了对象之间的一对多依赖,这样一来,当一个对象改变的时候,它的所有依赖者就会自动更新。
    // 而这个对象 就称之为 主题,这些依赖者就称之为 观察者

 

该模式的组成部分:

  •   主题    部分: 主题 的协议, 各个负责 具体实现 的主题;
  •   观察者 部分: 观察者协议,  各个观察者的具体实现类;

OO原则:

  1.   封装变化
  2.   多用组合,少用继承
  3.   针对接口编程,不针对实现编程
  4.   为交互对象之间的松耦合而设计 

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
原文地址:https://www.cnblogs.com/ziyeSky/p/4432096.html