设计模式02 - 观察者模式

02_观察者模式
定义:
观察者模式定义对象之间的 一对多 依赖,这样一来,当一个对象改变状态时,
它得所有依赖者都会收到通知并自动更新。
设计原则:
尽量做到交互得对象之间得松耦合设计。
松耦合设计:允许我们建造能够应对变化的、有弹性的OO系统,因为对象之间的互相依赖降低到最低。
简述:
这个模式可以让你的对象在发生某些事情时保持消息灵通。
出版者(主题, subject) + 订阅者(观察者, observer) = 观察者模式(一对多)
p.s. 在“01_设计者模式”中,主题数据变化时,对象不会被通知。

main.cpp

/**
 * @file main.cpp
 * @author JeffyGao (gaojune_better@qq.com)
 * @version 0.1
 * @date 2022-04-29
 * @copyright Copyright (c) 2022
 * 
 * 文件包含:
 *      Subject.h   主题
 *      Observer.h   观察者
 *      DisplayElement.h    数据展示
 */


#include <iostream>
#include "Subject.h"
#include "Observer.h"
#include "DisplayElement.h"

// 测试案例
int main( ){
    WeatherData* weatherData = new WeatherData();

    CurrentConditionsDisplay* currentConditionsDisplay = new CurrentConditionsDisplay(*weatherData);

    weatherData->SetMeasurements( 80, 65, 30.4f );
    weatherData->SetMeasurements( 82, 70, 29.8f );
    weatherData->SetMeasurements( 78, 90, 39.4f );

    return 0;
}

Observer.h

/**
 * @file Observer.h
 * @author JeffyGao (gaojune_better@qq.com)
 * @version 0.1
 * @date 2022-04-29
 * @copyright Copyright (c) 2022
 * 
 * @brief 观察者(Observer) 接口
 * 简介:
 *  本文件为 观察者(Observer) 的创建。
 * 所有的观察者都实现 Ovserver接口,所以它们都不得不实现 update() 方法。
 * 
 * 文件包含:
 *      class Observer  观察者
 *          Update( ) 更新数据
 */ 

#pragma once

#include <iostream>
#include "Subject.h"

class Observer{
public:
    Observer( ){
        std::cout << "ctor Observer" << std::endl;
    }
    ~Observer( ){
        std::cout << "dtor Observer" << std::endl;
    }

public:
    // 更新数据。
    // 当气象测量数据变化时观察者从 Subject获得的状态值。
    void Update( float tmep, float humidity, float pressure ){
        std::cout << "func_Update 温度: " << tmep << " 湿度: " << humidity << " 气压:" << pressure << std::endl;
    }
};

DisplayElement.h

/**
* @file DisplayElement.h
 * @author JeffyGao (gaojune_better@qq.com)
 * @version 0.1
 * @date 2022-04-29
 * @copyright Copyright (c) 2022
 * 
 * @brief 数据显示(DisplayElement) 接口
 * 简介:
 *  本文件为 数据显示(DisplayElement) 的创建。
 *  DiaplayElement接口只包含一个方法 Display(),当元素需要显示时,调用此方法。
 * 
 * 文件包含:
 *      class DiaplayElement    展示数据
 *          Display( ) 展示数据
 *      class CurrentConditionsDisplay : public Observer, public DisplayElement
 *          CurrentConditionsDisplay( ) 用它来把显示注册为观察者
 *          Update( )                   更新数据
 *          Display( )                  重写了 virtual DiaplayElement::Display() = 0
 */

#pragma once
#include <iostream>
#include "Subject.h"
#include "Observer.h"

// 前置声明
class Observer;

class DisplayElement{
public:
    DisplayElement( ){
        std::cout << "ctor DisplayElement" << std::endl;
    }
    ~DisplayElement( ){
        std::cout << "dtor DisplayElement" << std::endl;
    }

public:
    virtual void Display( ) = 0;
};

/**
 * 这个显示实现了 Observer接口,所以它可以从 WeatherData对象中获取变化
 * 它也实现了 DisplayElement,因为我们的 API 打算要求所有显示元素实现这个接口
*/
class CurrentConditionsDisplay : public Observer, public DisplayElement{
private:
    float _temperature;
    float _humidity;
    WeatherData _weatherData;

public:

    // ctor
    CurrentConditionsDisplay( ){
        std::cout << "CurrentConditionsDisplay ctor" << std::endl;
    }

    // 构造器被传入 weatherData对象( Subject ),我们用它来把显示注册为观察者
    CurrentConditionsDisplay( WeatherData weatherData ){
        std::cout << "CurrentConditionsDisplay( WeatherData weatherData ) ctor" << std::endl;

        this->_weatherData = weatherData;
        weatherData.RegisterObserver( *this );
    }

    // class Observer 里有定义
    void Update( float temperature, float humidity, float pressure ){
        this->_temperature = temperature;
        this->_humidity    = humidity;

        Display( );
    }

    // 重写了 virtual DiaplayElement::Display() = 0
    void Display( ){
        std::cout << "当前温度: " << _temperature << "  当前湿度: " << _humidity << std::endl;
    }

};

Subject.h

/**
 * @file Subject.h
 * @author JeffyGao (gaojune_better@qq.com)
 * @version 0.1
 * @date 2022-04-29
 * @copyright Copyright (c) 2022
 * 
 * @brief 主题 Subject
 * 简介:
 *  本文件为 主题(Subject)的创建
 * 
 * 文件包含:
 *      class Subject   主题
 *          RegisterObserver( )     注册 Observer
 *          RemoveObserver( )       移除 Observer
 *          NotifyObservers( )      当 Subject 的状态改变时,这个方法会被调用,以通知所有的观察者
 *      
 *      class WeatherData : public Subject           实现 Subject 接口
 *          WeatherData( )          构造 _observer
 *          RegisterObserver( )     注册 Observer
 *          RemoveObserver( )       移除 Observer
 *          NotifyObservers( )      把所有状态都告诉 观察者
 *          MeasurementsChanged( )  从气象站得到更新的测量值时,通知 Observer
 *          SetMeasurements( )      设置测量值
 */
#pragma once

#include <iostream>
#include <vector>
#include "Observer.h"

class Subject{
public:
    Subject( ){
        std::cout << "ctor Subject" << std::endl;
    }
    ~Subject( ){
        std::cout << "dtor Subject" << std::endl;
    }

public:
    // 注册 Observer
    void RegisterObserver( Observer o );
    // 移除 Observer
    void RemoveObserver( Observer o );
    // 当 Subject 的状态改变时,这个方法会被调用,以通知所有的观察者
    void NotifyObservers( );

};

// 实现 Subject 接口
class WeatherData : public Subject{
public:
    WeatherData( ){
        std::cout << "ctor WeatherData" << std::endl;

        _observer = std::vector<Observer>( );
    }
    ~WeatherData( ){
        std::cout << "dtor WeatherData" << std::endl;
    }

public:
    // 注册
    void RegisterObserver( Observer o ){
        std::cout << "RegisterObserver" << std::endl;
        //_observer->add( o );    
    }

    // 移除
    void RemoveObserver( Observer o ){
        std::cout << "RemoveObserver" << std::endl;
       // _observer->remove( o );
    }

    // 把所有状态都告诉 观察者
    // 因为它们都是 Observer,我们知道它们都实现了 update(),所以知道如何通知它们
    void NotifyObservers( ){
        std::cout << "func NotifyObservers()" << std::endl;
        
        int count_num = 1;
        std::cout << "begin NotifyObservers" << std::endl;

        // 不理解这里的写法,vector<Observer> 里面的数据代表什么?
        // for ( Observer &ob : _observer ){
        //     std::cout << " No. " << count_num++ << std::endl;
        //     ob.Update( _temperature, _humidity, _pressure );
        // }
        _observer[0].Update( _temperature, _humidity, _pressure );

    }

    // 从气象站得到更新的测量值时,通知 Observer
    void MeasurementsChanged( ){
        std::cout << "func MeasurementsChanged()" << std::endl;

        std::cout << "goto func NotifyObservers()" << std::endl;
        NotifyObservers( );
    }

    // 设置测量值
    void SetMeasurements( float temperature, float humidity, float pressure ){
        std::cout << "func SetMeasurements()" << std::endl;
        this->_temperature = temperature;
        this->_humidity    = humidity;
        this->_pressure    = pressure;

        // 数据改变了
        std::cout << "goto func MeasurementsChanged()" << std::endl;
        MeasurementsChanged( );
    }

    // 其它 WeatherData 的方法可以继续往后面写

private:
    std::vector<Observer> _observer;
    float _temperature;                  // 温度
    float _humidity;                    // 湿度
    float _pressure;                    // 气压
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值