观察者模式-Observer

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rl529014/article/details/82228891

概念解释

比较概念的解释是,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,然后具体观察者把自己注册到具体目标里,在具体目标发生变化时候,具体目标调度观察者的更新方法。

比如有个“天气中心”的具体目标A,专门监听天气变化,而有个显示天气的界面的观察者B,B就把自己注册到A里,当A触发天气变化,就调度B的更新方法,并带上自己的上下文。
这里写图片描述

代码示例:(代码基于Qt、C++)

#include <QCoreApplication>
#include <list>
#include <algorithm>
#include <iostream>
using namespace std;

//订阅者基类
class ObserverBoardInterface
{
public:
    virtual void update(float a,float b,float c) = 0;
};

//订阅者基类
class DisplayBoardInterface
{
public:
    virtual void show() = 0;
};

// The Abstract Subject
//发布者基类
class WeatherDataInterface
{
public:
    virtual void registerOb(ObserverBoardInterface* ob) = 0;
    virtual void removeOb(ObserverBoardInterface* ob) = 0;
    virtual void notifyOb() = 0;
};

// The Concrete Subject
//消息发布者
class ParaWeatherData: public WeatherDataInterface
{
public:
    void SensorDataChange(float a,float b,float c)
    {
        m_humidity = a;
        m_temperature = b;
        m_pressure = c;
        notifyOb(); //通知消息订阅者
    }

    void registerOb(ObserverBoardInterface* ob)
    {
        m_obs.push_back(ob);
    }

    void removeOb(ObserverBoardInterface* ob)
    {
        m_obs.remove(ob);
    }
protected:
    void notifyOb()
    {
        list<ObserverBoardInterface*>::iterator pos = m_obs.begin();
        while (pos != m_obs.end())
        {
            ((ObserverBoardInterface* )(*pos))->update(m_humidity,m_temperature,m_pressure);
            (dynamic_cast<DisplayBoardInterface*>(*pos))->show();
            ++pos;
        }
    }

private:
    float        m_humidity;
    float        m_temperature;
    float        m_pressure;
    list<ObserverBoardInterface* > m_obs; //存储消息订阅者
};

// A Concrete Observer
//消息订阅者
class CurrentConditionBoard : public ObserverBoardInterface, public DisplayBoardInterface
{
public:
    CurrentConditionBoard(ParaWeatherData& a):m_data(a)
    {
        m_data.registerOb(this);
    }
    void show()
    {
        cout<<"_____CurrentConditionBoard_____"<<endl;
        cout<<"humidity: "<<m_h<<endl;
        cout<<"temperature: "<<m_t<<endl;
        cout<<"pressure: "<<m_p<<endl;
        cout<<"_______________________________"<<endl;
    }

    void update(float h, float t, float p)
    {
        m_h = h;
        m_t = t;
        m_p = p;
    }

private:
    float m_h;
    float m_t;
    float m_p;
    ParaWeatherData& m_data;
};

// A Concrete Observer
//消息订阅者
class StatisticBoard : public ObserverBoardInterface, public DisplayBoardInterface
{
public:
    StatisticBoard(ParaWeatherData& a):m_maxt(-1000),m_mint(1000),m_avet(0),m_count(0),m_data(a)
    {
        m_data.registerOb(this);
    }

    void show()
    {
        cout<<"________StatisticBoard_________"<<endl;
        cout<<"lowest  temperature: "<<m_mint<<endl;
        cout<<"highest temperature: "<<m_maxt<<endl;
        cout<<"average temperature: "<<m_avet<<endl;
        cout<<"_______________________________"<<endl;
    }

    void update(float h, float t, float p)
    {
        ++m_count;
        if (t>m_maxt)
        {
            m_maxt = t;
        }
        if (t<m_mint)
        {
            m_mint = t;
        }
        m_avet = (m_avet * (m_count-1) + t)/m_count;
    }

private:
    float m_maxt;
    float  m_mint;
    float m_avet;
    int m_count;
    ParaWeatherData& m_data;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    ParaWeatherData * wdata = new ParaWeatherData; //发布者
    CurrentConditionBoard* currentB = new CurrentConditionBoard(*wdata); //注册订阅者
    StatisticBoard* statisticB = new StatisticBoard(*wdata); //注册订阅者

    wdata->SensorDataChange(10.2, 28.2, 1001); //发布消息
    wdata->SensorDataChange(12, 30.12, 1003);
    wdata->SensorDataChange(10.2, 26, 806);
    wdata->SensorDataChange(10.3, 35.9, 900);

    wdata->removeOb(currentB); //移除订阅者

    wdata->SensorDataChange(100, 40, 1900);

    delete statisticB;
    delete currentB;
    delete wdata;

    return a.exec();
}

其实观察者模式还是挺容易理解的,如果你还没有理解的话,
我再举一个栗子,通过下面的描述,在配合上面的程序demo,会更加容易理解观察者模式。

  • 需求:
    有用户A、B、C三个人,我们称呼他们为订阅者;报社机构D,负责记录订阅者的信息,并配送报纸。
  • 订阅者注册:
    A、B、C三个人如果想要每天能够阅读最新的报纸,就需要到D那里去提出申请,并留存报箱地址,D将报纸订阅者的报箱位置记录下来。
  • 发布者发布消息:
    每天早上,D会根据自己的记录本,按顺序投递报纸到对应的订阅者的报箱。

(此处不区分观察者模式和发布者订阅者模式的区别)

猜你喜欢

转载自blog.csdn.net/rl529014/article/details/82228891