1. 程式人生 > >C++設計模式--觀察者模式

C++設計模式--觀察者模式

觀察者模式定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。

                                                                                                                                                   --《Head First》設計模式

                             

                                                                             圖片來自網路

C++實現觀察者模式:

主題物件:

//weatherdata.h
#ifndef __WEATHERDATA_H__
#define __WEATHERDATA_H__

#include <list>
#include "currentconditionsdisplay.h"

class Observer;

//主題物件,負責註冊,刪除,通知觀測者
class Subject
{
public:
    Subject();
    ~Subject();
    virtual void RegisterObserver(Observer* o);
    virtual void RemoveObserver(Observer* o);
    virtual void NotifyObserver();
};


class WeatherData : public Subject
{

public:
    WeatherData();
    virtual ~WeatherData();
    void setMeasurements(float temperature,float humidity,float pressure);

public:
    virtual void RegisterObserver(Observer* o) override;
    virtual void RemoveObserver(Observer* o) override;
    virtual void NotifyObserver() override;

private:
    void MeasurementsChanged();
private:
    std::list<Observer*> observers;
    float m_temperature;
    float m_humidity;
    float m_pressure;
};
#endif

主題物件實現:

//weatherdata.cc
#include "weatherdata.h"

Subject::Subject()
{
}

Subject::~Subject()
{
}

void Subject::RegisterObserver(Observer* o)
{
}

void Subject::RemoveObserver(Observer* o)
{
}

void Subject::NotifyObserver()
{
}

WeatherData::WeatherData():Subject()
{
}

WeatherData::~WeatherData()
{
}

void WeatherData::RegisterObserver(Observer* o)
{
    if (o)
        observers.push_back(o);
}
void WeatherData::RemoveObserver(Observer* o)
{
    if (o)
        observers.remove(o);
}

void WeatherData::NotifyObserver()
{
    for (auto x : observers)
        x->Update(m_temperature,m_humidity,m_pressure);
}

void WeatherData::setMeasurements(float temperature,
                            float humidity,float pressure)
{
    m_temperature = temperature;
    m_humidity = humidity;
    m_pressure = pressure;
    //通知觀察者
    MeasurementsChanged();
}

void WeatherData::MeasurementsChanged()
{
    NotifyObserver();
}

觀察者物件:

//currentconditionsdisplay.h
#ifndef __CURRENTCONDITIONSDISPLAY_H__
#define __CURRENTCONDITIONSDISPLAY_H__

#include "weatherdata.h"

class Subject;

class Observer
{
public:
    Observer();
    virtual void Update(float temperature,
                            float humidity,float pressure);
};


class CurrentConditionsDisplay : public Observer
{
public:
    CurrentConditionsDisplay(Subject* subject);
    virtual void Update(float temperature,
                                float humidity,float pressure);

private:
    void display();

private:
    float m_temperature;
    float m_humidity;
    float m_pressure;

    Subject* m_subject;
};

#endif
//currentconditionsdisplay.cc
#include <iostream>
#include "currentconditionsdisplay.h"

Observer::Observer()
{
}

void Observer::Update(float temperature,
                            float humidity,float pressure)
{
}

CurrentConditionsDisplay
        ::CurrentConditionsDisplay(Subject* subject)
        :m_subject(subject)
{
    m_subject->RegisterObserver(this);
}

void CurrentConditionsDisplay::Update(float temperature,
                                float humidity,float pressure)
{
    m_temperature = temperature;
    m_humidity = humidity;
    m_pressure = pressure;
    
    display();
}

void CurrentConditionsDisplay::display()
{
    std::cout << "CurrentConditions : (temperature : " << m_temperature
         << "),(humidity : " << m_humidity << "),(pressure : "<<m_pressure
         <<")"<<std::endl;
}

主函式:

//main.cc
#include <unistd.h>

#include "weatherdata.h"
#include "currentconditionsdisplay.h"

int main()
{
    WeatherData weatherData;
    CurrentConditionsDisplay currentConditionsDisplay(&weatherData);
    float temperature = 25.5;
    float humidity = 85;
    float pressure = 20;
    while(true){
        weatherData.setMeasurements(temperature++,humidity--,pressure++);
        sleep(1);
    }
    return 0;
}

主函式每隔1秒修改一次主題物件,主題物件更新後通知觀察者。

Linux下編譯:

g++ -std=c++11 -o main main.cc currentconditionsdisplay.cc weatherdata.cc
./main