c++实现观察者模式

观察者模式是一种比较基础、普遍的设计模式,它定义的是对象间的依赖关系:当某一对象的状态改变时,它会主动通知所有对应的观察者对象,以便后者能及时作出响应。


想起大学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========================



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值