程诚成
勤奋,踏实,在生活中学习,在学习中快乐……
posts - 13,comments - 27,trackbacks - 0
    观察者(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;
}

    由于是开始学习,肯定有很多因素考虑不到,欢迎大家批评指正,共同进步!    

Tag标签: 设计模式
posted on 2008-04-24 13:50 程、诚、成 阅读(488) 评论(2)  编辑 收藏 网摘 所属分类: 设计模式(DesignPatten)

FeedBack:
2008-07-13 18:24 | ptrjeffrey [未注册用户]
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);
}
}
这里使用while?
一次删除一个地址
嗯,而且同一个观察者如何多次请求的话就会删除不干净了.哈哈

  回复  引用    
2008-07-13 18:25 | ptrjeffrey [未注册用户]
用while肯定会出错!
如果找到iter的话,它会一直删除...汗
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-04-29 16:30 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:


相关搜索:
设计模式

相关链接: