C++观察者模式

/**********************************************************************************************************************/
* 观察者模式
* [说明]
*  在一公文处理系统中,开发者定义了一个公文类OfficeDoc, 其中定义了公文具有的属性和处理公文的相应方法。当公文件的内容或
* 状态发生变化时,关注此OfficeDoc 类对象的相应的DocExplorer 对象都要更新其自身的状态。一个OfficeDoc 对象能够关联一组
* DocExplorer 对象。当OfficeDoc 对象的内容或状态发生变化时,所有与之相关联的DocExplorer对象都将得到通知,这种应用被称
* 为观察者模式。
*
* 例如MFC的DOC、VIEW架构都是基于这种观察者的模式。
/**********************************************************************************************************************/


/**********************************************************************************************************************/
* 本代码还用了一种标示的方法实现了在运行时辨识对象。
* RTTI只能在运行时实现类型的识别。没法实现对象的识别。
/**********************************************************************************************************************/

#include <stdio.h>
#include <typeinfo>

// 最多与OfficeDoc关联的DocExplorer对象的个数
const int OBS_MAX = 20;

class COfficeDoc;

// 关注OfficeDoc公文对象的类
//##ModelId=44D02B1A01B9
class CDocExplorer
{
public:
 //##ModelId=44D02B1A01BA
 CDocExplorer(COfficeDoc *doc);
 //##ModelId=44D02B1A01BC
 void UpdateSelf(COfficeDoc *doc);

 // 为了实现对象的识别,在此加一个标示
 //##ModelId=44D02B1A01BE
 int nExplorerID;
};

//##ModelId=44D02B1A01D4
class COfficeDoc
{
public:
 //##ModelId=44D02B1A01D5
 COfficeDoc()
 {
  index = 0;
 }
 
 //##ModelId=44D02B1A01D6
 void Attach(CDocExplorer *e)
 {
  if(index >= OBS_MAX || e == NULL)
  {
   return;
  }
  myObs[index] = e;
  index++;

  e->nExplorerID = index;
 }

 //##ModelId=44D02B1A01E4
 void Detach(CDocExplorer *e)
 {
  for(int i = 0; i <index; i++)
  {
   if(myObs[i] == e)
   {
    // 把当前位置的观察者对象和最后一个对象交换,并把index的值减一个
    if(i <= index-2)
     myObs[i] = myObs[index-1];
    myObs[index - 1] = NULL;
    index--;
    break;
   }
  }
 }
 
 // 修改数据,并通知观察者更新
 //##ModelId=44D02B1A01E6
 void ModifyData(int data)
 {
  printf("公文的数据改变成:%d/n", data);
  m_nData = data;
  NotifyObs();
 }

private:
 //##ModelId=44D02B1A01E9
 CDocExplorer *myObs[OBS_MAX];  // 观察者的类对象指针数组
 //##ModelId=44D02B1A01F4
 int index;

 // 通知所有的观察者对象改变自己的状态
 //##ModelId=44D02B1A01F5
 void NotifyObs()
 {
  for(int i = 0; i < index; i++)
  {
   myObs[i]->UpdateSelf(this);
  }
 }
 
public:
 // 公文的数据
 //##ModelId=44D02B1A01F6
 int m_nData;
};


//##ModelId=44D02B1A01BA
CDocExplorer::CDocExplorer(COfficeDoc *doc)
{
 doc->Attach(this); 
}

//##ModelId=44D02B1A01BC
void CDocExplorer::UpdateSelf(COfficeDoc *doc)
{
 // 把下面两行的注释打开还可以看到typeid和type_info的用法
 // 会发现typeid只能实现类型的识别

 //const type_info &t = typeid(*doc);
 //printf("我正在观察%s/n", t.name());
 
 printf("我是观察者%d, ", nExplorerID);
 printf("更新数据: %d /n", doc->m_nData);   
}

 

int main()
{
 COfficeDoc officeDoc;
 CDocExplorer docExplorer0(&officeDoc);
 CDocExplorer docExplorer1(&officeDoc);
 CDocExplorer docExplorer2(&officeDoc);
 CDocExplorer docExplorer3(&officeDoc);
 CDocExplorer docExplorer4(&officeDoc);
 
 // 更新公文的数据
 officeDoc.ModifyData(123);
 printf("/n");
 officeDoc.ModifyData(567);
 
 return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值