观察者模式是一种比较基础、普遍的设计模式,它定义的是对象间的依赖关系:当某一对象的状态改变时,它会主动通知所有对应的观察者对象,以便后者能及时作出响应。
想起大学C++老师经常挂在嘴边的一句英文:“Don't call me, I‘ll call you.” 细细想来,这句话其实和观察者模式有一些共通之处。而无论是在程序世界还是现实世界,如果我们在合适的场合将观察者模式应用得当,就可以在时效性、效率方面得到巨大的收益。
用C++实现观察者模式时,可以借助回调函数,但用起来不是那么简易。我们可以让观察者提供一个统一的接口,这样被观察者就能够在需要的时候调用这个接口,送达通知。而通知的形式——也就是接口的定义,可以有两种:
1. 被观察者只发送一个空的通知;观察者得到通知后,自行去获取被观察者的状态,然后作出响应。
2. 被观察者将状态信息一并发送给观察者;观察者可根据该通知的内容直接作出响应。
这里只实现第二种方式,代码如下:
1. 被观察者接口定义:
/********************
* IObservable.h
*******************/
#pragma once
#include "IObserver.h"
class IObservable
{
public:
// 注册观察者.
virtual void Register(IObserver* observer) = 0;
// 注销观察者.
virtual void UnRegister(IObserver* observer) = 0;
// 提供给第三方的功能:对本对象的状态作出修改。
virtual void SetState(int nState) = 0;
};
2. 观察者接口定义:
/*******************
* IObserver.h
******************/
#pragma once
class IObserver
{
public:
// 供被观察者调用,发送通知。
virtual void Update(int nState) = 0;
};
3. 目标类声明:
/*************
* Subject.h
*************/
#pragma once
#include "IObservable.h"
#include <set>
using namespace std;
class Subject: public IObservable
{
private:
int m_nState;
set<IObserver*> m_Observers;
public:
Subject();
~Subject();
void Register(IObserver* observer);
void UnRegister(IObserver* observer);
void SetState(int nState);
private:
// 通知各观察者.
void Notify();
};
4. 观察者具体类声明:
/*******************
* Observer.h
******************/
#pragma once
#include "IObserver.h"
#include "IObservable.h"
class Observer: public IObserver
{
private:
// 观察者的ID.
int m_nId;
public:
Observer(int id);
~Observer();
void Observe(IObservable* observable);
void UnObserve(IObservable* observable);
void Update(int nState);
};
5. 目标类具体实现:
/**********************
* Subject.cpp
*********************/
#include "Subject.h"
Subject::Subject()
:m_nState(0)
{
}
Subject::~Subject()
{
}
// 注册观察者.
void Subject::Register(IObserver* pObserver)
{
this->m_Observers.insert(pObserver);
}
// 注销观察者.
void Subject::UnRegister(IObserver* pObserver)
{
this->m_Observers.erase(pObserver);
}
// 修改状态.
void Subject::SetState(int state)
{
this->m_nState = state;
// 通知.
this->Notify();
}
// 通知所有观察者.
void Subject::Notify()
{
set<IObserver*>::iterator iter;
for(iter=m_Observers.begin(); iter != m_Observers.end(); iter++)
{
(*iter)->Update(m_nState);
}
}
6. 观察者具体类实现:
/*****************
* Observer.cpp
****************/
#include "Observer.h"
#include <stdio.h>
Observer::Observer(int id)
{
m_nId = id;
}
Observer::~Observer()
{
}
// 观察目标
void Observer::Observe(IObservable* pObservable)
{
if(!pObservable)
return;
pObservable->Register(this);
printf("观察者【%d】 开始观察目标 \n", m_nId);
}
// 停止观察目标.
void Observer::UnObserve(IObservable* pObservable)
{
if(!pObservable)
return;
pObservable->UnRegister(this);
printf("观察者【%d】 停止观察.\n", m_nId);
}
// 获得状态更新.
void Observer::Update(int nState)
{
printf(" 观察者【%d】 获得状态更新: %d \n", m_nId, nState);
}
7. 测试代码:
/****************************
* ObserverPatternTest.cpp
***************************/
#include "Subject.h"
#include "Observer.h"
int main()
{
// 观察者个数.
const int nObserverNum = 3;
// 目标.
Subject* pSubject = new Subject();
// 观察者群.
Observer* pObservers[nObserverNum];
// 所有观察者都进行观察.
for(int i=0; i<nObserverNum; i++)
{
pObservers[i] = new Observer(i);
pObservers[i]->Observe(pSubject);
}
int state;
// 改变目标状态.
state = 1;
printf("\n第三只手改变目标状态:%d. \n", state);
pSubject->SetState(state);
printf("\n");
// 第一个观察者停止观察.
pObservers[0]->UnObserve(pSubject);
// 改变目标状态.
state = 2;
printf("\n第三只手改变目标状态:%d. \n", state);
pSubject->SetState(state);
printf("\n");
// 清理.
delete pSubject;
for(int i=0; i<nObserverNum; i++)
{
delete pObservers[i];
}
return 0;
}
运行结果:
=======================End========================