HEAD FIRST设计模式之观察者模式

作者: 微微笑的蜗牛 | 来源:发表于2016-01-24 14:44 被阅读187次

    定义

    观察者模式有主题和观察者,主题可以订阅多个观察者,当主题发生变化时,通知观察者来做相应改变。

    UML图

    Paste_Image.png

    定义了一个主题接口,可添加,删除,通知观察者。
    定义了一个观察者接口,在收到主题变化通知后,做出变化。

    实现例子

    拿Head First上面的气象站的例子来说吧。

    需要实现的功能大致是这样:

    根据气象站的测量接口数据的变化(有个WetherData的类来提供数据),显示天气数据的board必须立即更新。有“目前状况”,“气象统计”,“天气预报”三块board。系统必须可扩展,可随意添加/删除board。

    其实,这就比较适合用观察者模式,WetherData为subject,当有更新时,通知到board,来更新数据显示。

    github地址在这里,来戳吧

    代码如下:

    观察者,主题接口

    // 主题接口
    protocol ISubject {
        func addObserver(observer: BaseObserver)
        func removeObserver(observer: BaseObserver)
        func notifyObservers()
    }
    
    // 观察者接口
    protocol IObserver {
        func update(subject: ISubject)
    }
    
    class BaseObserver: IObserver {
        
        var value: Int = {
            let now = NSDate()
            let timeInterval = now.timeIntervalSince1970 * 100000
            let interval: Int = Int(timeInterval)
            
            print(interval)
            return interval
        }()
        
        func update(subject: ISubject) {
            fatalError("subclass should implement this method")
        }
    }
    
    extension BaseObserver: Equatable, Hashable {
        var hashValue: Int {
            return self.value
        }
    }
    
    func ==(lhs: BaseObserver, rhs: BaseObserver) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
    
    

    本来只想定义个IObserver,addObserver(observer: IObserver),但是
    removeObserver(observer: IObserver)中,swift没有像oc那样removeObject的方法,只得自己实现Equatable, Hashable来判断是否是同一个对象,来进行删除。所以这里就采用了定义基类BaseObserver,采用时间hash,让其具有唯一性。

    如果有其他好的方法欢迎指出😄

    WeatherData

    class WeatherData: ISubject {
        
        private var observers: [BaseObserver] = []
        private var temperature: Float = 0
        private var humidity: Float = 0
        private var pressure: Float = 0
        
        func addObserver(observer: BaseObserver) {
            observers.append(observer)
        }
        
        func removeObserver(observer: BaseObserver) {
            observers = observers.filter({
                $0 != observer
            })
        }
        
        func notifyObservers() {
            for observer in observers {
                observer.update(self)
            }
        }
        
        func updateMeasurements(temperature: Float, _ humidity: Float, _ pressure: Float) {
            self.temperature = temperature
            self.humidity = humidity
            self.pressure = pressure
            
            self.notifyObservers()
        }
        
        // 温度
        func getTemperature() -> Float {
            return self.temperature
        }
        
        // 湿度
        func getHumidity() -> Float {
            return self.humidity
        }
        
        // 气压
        func getPressure() -> Float {
            return self.pressure
        }
    }
    
    

    当前状态board,其他的board类似

    // 目前状况
    class CurrentConditionDisplay: BaseObserver {
        
        init(subject: ISubject) {
            super.init()
            subject.addObserver(self)
        }
        
        override func update(subject: ISubject) {
            if let data = subject as? WeatherData {
                let temperature = data.getTemperature()
                let humidity = data.getHumidity()
                let pressure = data.getPressure()
                
                print("temperature:\(temperature), humidity:\(humidity), pressure:\(pressure)")
            }
        }
    }
    
    

    最终调用:

    // observer
    let weatherData = WeatherData()
    let currentDisplay = CurrentConditionDisplay(subject: weatherData)
    let statsticsDisplay = StatsticsDisplay(subject: weatherData)
    let forcastDisplay = ForecastDisplay(subject: weatherData)
    
    weatherData.updateMeasurements(10, 1, 200)
    
    

    输出:

    temperature:10.0, humidity:1.0, pressure:200.0

    最大气压为:200.0

    明天的天气为晴,5~10°,无风

    若加上weatherData.removeObserver(currentDisplay)
    则不会输出当前状态

    最大气压为:200.0

    明天的天气为晴,5~10°,无风

    相关文章

      网友评论

        本文标题:HEAD FIRST设计模式之观察者模式

        本文链接:https://www.haomeiwen.com/subject/sdbrkttx.html