设计模式之观察者模式
对于设计模式,我的认识还不是很深,也许我在用,但是,并不能把它上升到理论的高度,到目前为止,我可能最为熟悉的应该是MFC的那一套,下一次,我准备把WINDOWS的消息机制做一个自己的总结。而今天,我想谈的一种设计模式,我觉得很棒,至少在我看来很有实用价值,理解起来也很自然,而且,我自己把这种观察者模式称为“教师学生授课模式”。
编过WINDOW程序的人对消息一定不陌生,这一机制也确实给编程带来了极大的方便,在有了面向对象的思想以后,这一机制则更好发展成为一种易于理解,更接近现实的模型。两个对象之间可以通过发送消息来进行通信。(我记得在多线程里也有这样一种方式,意义上更为广泛),我把教师和学生都看做对象,在现实生活中很明显,当上课铃一响的时候,就在这两个类之间建立了一种关系,抽象一点就是一对多,一名教师,多个学生,学生观察老师的行为,老师向学生“广播”知识,同时,学生也相应的对一点的消息产生回应。这就是一个基本的观察者模型,一个目标(教师)、多个观察者(学生),他们通过消息(广播)产生交互。大家可以想想,这样一个模型在我们的程序设计中可能会经常的出现,如果可以通过继承的手段把这样一个模型做为基类,则派生出来的新类也就天生具有了消息传送机制,这是何等的方便,想到MFC为了实现一个消息机制采用了大量的宏等等复杂的技术,而我们现在通过这样一种很简单的方法,就可以做出一个用起来很简洁的代码组织风格。它最大的好处还是在于各个模块之间可以通过这种机制达到一种松偶合,代码可以最大限度的复用。好了,理论就说到这,(我很讨厌理论)如何用代码来实现这样一个模型呢?三个步骤:
一:设计一个对象列表类,用于“教师”存放“学生”列表。也可以为学生存放教师列表。
二:设计教师类。
三:设计学生类。
#ifndef __H_CObjectList__
#define __H_CObjectList__
#include <afxcoll.h>
class CObjectList : public CPtrArray
{
public:
CObjectList(void);
virtual ~CObjectList(void);
int GetIndex(void * inPointer);
int Add(void * inPointer);
int Add(void * inPointer, int inIndex);
void Remove(void * inPointer);
void * GetPrevious(void * inPointer);
void * GetNext(void * inPointer);
};
#endif
#define __H_CObjectList__
#include <afxcoll.h>
class CObjectList : public CPtrArray
{
public:
CObjectList(void);
virtual ~CObjectList(void);
int GetIndex(void * inPointer);
int Add(void * inPointer);
int Add(void * inPointer, int inIndex);
void Remove(void * inPointer);
void * GetPrevious(void * inPointer);
void * GetNext(void * inPointer);
};
#endif
上面是通用的对象列表类。
#ifndef __H_CMsgStation__
#define __H_CMsgStation__
#include "CObjectList.h"
typedef long MessageT;
typedef long NotifyT;
class CMsgReceiver;
class CMsgStation
{
protected:
CObjectList mReceivers;
public:
CMsgStation(void);
virtual ~CMsgStation(void);
void AddMsgReceiver(CMsgReceiver * inReceiver);
void RemoveMsgReceiver(CMsgReceiver * inReceiver);
bool Broadcast(MessageT inMessage, void * ioParam = 0, void * ioParam2 = 0);
bool Notify(NotifyT inNotification, long inParam1 = 0, long inParam2 = 0);
};
const MessageT msg_StationDestroyed = 0;
const MessageT msg_Notify = 1;
struct SNotificationStruct
{
NotifyT mNotification;
CMsgStation * mStation;
long mParam1;
long mParam2;
};
#endif // __H_CMsgStation__
#define __H_CMsgStation__
#include "CObjectList.h"
typedef long MessageT;
typedef long NotifyT;
class CMsgReceiver;
class CMsgStation
{
protected:
CObjectList mReceivers;
public:
CMsgStation(void);
virtual ~CMsgStation(void);
void AddMsgReceiver(CMsgReceiver * inReceiver);
void RemoveMsgReceiver(CMsgReceiver * inReceiver);
bool Broadcast(MessageT inMessage, void * ioParam = 0, void * ioParam2 = 0);
bool Notify(NotifyT inNotification, long inParam1 = 0, long inParam2 = 0);
};
const MessageT msg_StationDestroyed = 0;
const MessageT msg_Notify = 1;
struct SNotificationStruct
{
NotifyT mNotification;
CMsgStation * mStation;
long mParam1;
long mParam2;
};
#endif // __H_CMsgStation__
上面是目标类(可以理解为消息站)
#ifndef __H_CMsgReceiver__
#define __H_CMsgReceiver__
#include "CMsgStation.h"
class CMsgReceiver
{
protected:
CObjectList mStations;
public:
CMsgReceiver(void);
virtual ~CMsgReceiver(void);
void AddMsgStation(CMsgStation * inStation);
void RemoveMsgStation(CMsgStation * inStation);
virtual bool ReceiveMessage(MessageT inMessage, void * ioParam,
void * ioParam2);
virtual bool Respond(NotifyT inNotification, CMsgStation * inStation,
long inParam1, long inParam2);
};
#endif // __H_CMsgReceiver__
这是观察者类。(可以理解为消息的接受者)#define __H_CMsgReceiver__
#include "CMsgStation.h"
class CMsgReceiver
{
protected:
CObjectList mStations;
public:
CMsgReceiver(void);
virtual ~CMsgReceiver(void);
void AddMsgStation(CMsgStation * inStation);
void RemoveMsgStation(CMsgStation * inStation);
virtual bool ReceiveMessage(MessageT inMessage, void * ioParam,
void * ioParam2);
virtual bool Respond(NotifyT inNotification, CMsgStation * inStation,
long inParam1, long inParam2);
};
#endif // __H_CMsgReceiver__
通过上面的代码不难看出,教师通过AddMessageReceiver()方法来增加一个新的消息接收者,同样在这个方法里,会调用接受者的AddMsgStation()方法,来把这个目标类,放在自己的列表中,完成一个互相通知的过程。再由教师通过Broadcast()方法向他所持有的所用观察者发送消息,在这个函数里,通过调用观察者的ReceiveMessage()方法来达到发送的目的,这种模式有点象COM里的“推”的模式。Respond,Notify 这两个方法是什么意思呢,呵呵,很简单,有的时候会有几个老师在不同的时间给学生布置作业,做为学生你总得知道是哪个老师布置的吧,如果不搞清楚就乱做,小心补考噢!
以上就是我对这种模式的理解,以后,我还会自己想一些关于这个模式的应用,等到有成熟的想法之后再贴上来,大家一起交流,以上言论一定有不准确的地方还望指正。
主要参考了下面两本书
1:《DirectShow实务精选》
2: 《设计模式,可复用面向对象基础》