C++ 实现观察者(Observer)模式详解

来源:互联网 发布:开源手机网站源码 编辑:程序博客网 时间:2024/04/29 04:00
    观察者(Observer)模式,是常见的模式之一。比如一份报纸,有很多订户。订阅者并不知道报纸何时会送来,他只知道自己订了这份报纸。订阅者在这里担任着观察者的角色,而报社则是被观察者。
    报纸一旦印刷完毕,就应该及时送到订户手中,如果将报社看作一个对象,则报纸便是观察者(订户)和被观察者(报社)之间的纽带。观察者需要维护一个与报纸相关的变量或函数,在这个具体问题中,这个变量就是订户是否收到报纸,可设置为一个布尔型,当收到时,订户需要更新这个变量。

    下面是源码:
// "Observer.H"#ifndef _OBSERVER_H_#define _OBSERVER_H_#include <list>using namespace std;class Observer;/* 被观察者接口 */class Subject{public:    Subject():m_Issue(0)    {    }    void Attach(Observer *oo);//订阅此对象    void Detach(Observer *oo);//解除订阅    void Notify();//通知订阅者更新    void virtual Issue() = 0;//发行函数    bool GetIssue()    {        return m_Issue;    }    ~Subject()    {        list<Observer*>::iterator iter1,iter2,temp;        for (iter1 = m_observerList.begin(), iter2 = m_observerList.end();        iter1 != iter2;        )        {            temp = iter1;            ++iter1;            m_observerList.erase(temp);        }        m_observerList.clear();    }protected:    bool m_Issue;//发行标志    list<Observer*> m_observerList;//订阅者队列};/*观察者接口*/class Observer{public:    Observer():m_receive(0){};    void virtual Update()//更新函数    {    }    void virtual ShowMessage() = 0;//模拟与被观察者相关的函数protected:    bool m_receive;//收到报纸标志};/* 具体的被观察者 */class ConcreteSubject:public Subject{public:    ConcreteSubject()    {}    void Issue();    };/* 具体的观察者 */class Subscriber1:public Observer{public:    void virtual Update();    void ShowMessage();};class Subscriber2:public Observer{public:    void virtual Update();    void ShowMessage();};#endif

    被观察者接口说明:
        1.订阅对象、解除订阅、通知更新的函数,是所有被观察者共有行为,所以将其抽象出来作为被观察者的接口。
        2.发行函数模拟改变状态函数,因为不同的被观察者有不同的方式,所以将其声明为纯虚函数,在派生类中实现。
        3.观察者用STD中的List模板来实现,所以需要析构函数来释放。
    观察者接口说明:
        1.由于所有观察者都有更新状态这一操作,所以将其声明为接口。
        2.Update()函数对于不同的具体对象,有不同的行为,所以在派生类中实现,声明为纯虚函数。
        3.ShowMessage()函数用来模拟与被观察者相关的操作,如果被观察者状态改变,观察者需要执行某种操作,则在这里实现。本例中用来显示收到报纸这一信息。

    下面是类的实现部分:Observer.cpp

#include "Observer.H"#include <algorithm> #include <iostream>/* 订阅报纸 */void Subject::Attach(Observer *oo){    m_observerList.push_back(oo);}/* 取消订阅 */void Subject::Detach(Observer *oo){    list<Observer*>::iterator iter;    iter = std::find(m_observerList.begin(),m_observerList.end(),oo);    while(iter != m_observerList.end())    {        m_observerList.erase(iter);    }}/*通知更新*/void Subject::Notify(){    list<Observer*>::iterator iter=m_observerList.begin();    for ( ; iter != m_observerList.end(); iter++)    {        (*iter)->Update();    }}/* 更改状态 */void ConcreteSubject::Issue(){    this->m_Issue = !this->m_Issue;    if ( this->m_Issue )    {        cout << "Magazine is Issued!\n";        this->Notify();        this->m_Issue = false;    }    }/*订阅者更新*/void Subscriber1::Update(){    this->m_receive = true;    this->ShowMessage();    this->m_receive = false;}void Subscriber1::ShowMessage(){    cout << "Subscriber1 has received the newspapers!\n";}/*订阅者更新*/void Subscriber2::Update(){    this->m_receive = true;    this->ShowMessage();    this->m_receive = false;}void Subscriber2::ShowMessage(){    cout << "Subscriber2 has received the newspapers!\n";}


    下面是主程序部分:
#include "Observer.H"#include <iostream>int main(){    Subject *sub=new ConcreteSubject(); //被观察者    Observer *customer1 = new Subscriber1();//观察者1    Observer *customer2 = new Subscriber2();//观察者2    sub->Attach(customer1);//观察者1订阅报纸    sub->Attach(customer2);//观察者2订阅报纸        if (sub->GetIssue())    {        cout << "Newspapers has issued!\n";    }    else    {        cout << "Newspapers has not issued!\n";    }    sub->Issue();       //发行报纸    cout<<endl;    if (sub->GetIssue())    {        cout << "Newspapers has issued!\n";    }    else    {        cout << "Newspapers has not issued!\n";    }    sub->Detach(customer1);//观察者1取消订阅    sub->Issue();        //发行报纸    return 0;}




0 0
原创粉丝点击