程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 《ASCE1885的設計模式》---觀察者模式

《ASCE1885的設計模式》---觀察者模式

編輯:C++入門知識

觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動更新。這一模式鎮中關鍵對象是目標(subject)和觀察者(observer)。一個目標可以有任意數目的依賴於它的觀察者。一旦目標的狀態發生改變,所有觀察者都得到通知。作為對這個通知的響應,每個觀察者都將查詢目標以使其狀態與目標的狀態同步。這種交互又稱為發布-訂閱模式。目標是通知的發布者,它發出通知時並不需要知道誰是它的觀察者,可以有任意數目的觀察者訂閱並接收通知。

 

觀察者模式的適用情況如下:

1)當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面;將這兩者封裝在獨立的對象總以使它們可以各自獨立地改變和復用;

2)當一個對象的改變需要同時改變其他對象,而不知道具體有多少個對象有待改變;

3)當一個對象必須通知其他對象,而它又不能假定其他對象是誰。即我們不希望這些對象是緊密耦合的。

 

觀察者模式結構圖如下:

 \


 

觀察者模式涉及到:

1)目標Subject:

目標知道它的觀察者,可以有任意多個觀察者觀察同一個目標;提供注冊和刪除觀察者對象的接口;

2)觀察者Observer:

為那些在目標發生改變時需獲得通知的對象定義一個更新接口;

3)具體目標ConcreteSubject:

將有關狀態存入各ConcreteObserver對象;當它的狀態發生改變時,向它的各個觀察者發出通知;

4)具體觀察者ConcreteObserver:

維護一個指向ConcreteSubject對象的引用;存儲有關狀態,這些狀態應與目標的狀態保持一致;實現Observer的更新接口以使自身狀態與目標的狀態保持一致;

 

實現:

觀察者接口:

class Subject;

class Observer

{

public:

         virtual ~Observer();

         virtual void Update(Subject* m_subject) = 0;

protected:

         Observer();

};

這種實現方式支持一個觀察者有多個目標,當觀察者觀察多個目標時,作為參數傳遞給Update操作的目標讓觀察者可以判定是哪一個目標發生了改變。

 

目標接口:

class Subject

{

public:

         virtual ~Subject();

         virtual void Attach(Observer*);

         virtual void Detach(Observer*);

         virtual void Notify();

protected:

         Subject();

private:

         std::list<Observer*> *_observers;

};

 

Subject::Subject()

{

         //記得使用前初始化

         _observers = new std::list<Observer*>;

}

 

void Subject::Attach(Observer* observer)

{

         _observers->push_back(observer);

}

 

void Subject::Detach(Observer* observer)

{

         if(observer != NULL)

                   _observers->remove(observer);

}

 

void Subject::Notify()

{

         std::list<Observer*>::iterator it = _observers->begin();

         while(it != _observers->end())

         {

                   (*it)->Update(this);

                   ++it;

         }

}

 

下面的例子是從維基百科上得來的:

#include <list>

#include <vector>

#include <algorithm>

#include <iostream>

using namespace std;

 

// The Abstract Observer

class ObserverBoardInterface

{

public:

    virtual void update(float a,float b,float c) = 0;

};

 

// Abstract Interface for Displays

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(WeatherDataInterface& 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;

    WeatherDataInterface& m_data;

};

 

// A Concrete Observer

class StatisticBoard : public ObserverBoardInterface, public DisplayBoardInterface

{

public:

    StatisticBoard(WeatherDataInterface& 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;

    WeatherDataInterface& m_data;

};

 

 

int main(int argc, char *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 0;

}

 

摘自 ASCE1885

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved