您的位置:首页 > 编程语言 > C语言/C++

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

2015-08-27 22:00 531 查看
观察者(Observer)模式,是常见的模式之一。比如一份报纸,有很多订户。订阅者并不知道报纸何时会送来,他只知道自己订了这份报纸。订阅者在这里担任着观察者的角色,而报社则是被观察者。

报纸一旦印刷完毕,就应该及时送到订户手中,如果将报社看作一个对象,则报纸便是观察者(订户)和被观察者(报社)之间的纽带。观察者需要维护一个与报纸相关的变量或函数,在这个具体问题中,这个变量就是订户是否收到报纸,可设置为一个布尔型,当收到时,订户需要更新这个变量。

#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();//清理list
    }
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()函数用来模拟与被观察者相关的操作,如果被观察者状态改变,观察者需要执行某种操作,则在这里实现。本例中用来显示收到报纸这一信息。

#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);
	//在list队列中查找是否有订阅者oo
    while(iter != m_observerList.end())
    {
        m_observerList.erase(iter);//在list队列中删除掉查找到的订阅者oo
		break;
    }
}

/*通知更新*/
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 )//如果发行标志为true
    {
        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;
}
测试结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: