当前位置:编程学习 > C/C++ >>

《ASCE1885的设计模式》---观察者模式

观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。这一模式镇中关键对象是目标(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;

     

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,