观察者模式是一种行为设计模式,主要用于实现一种订阅机制,可在目标事件发生变化时告知所有观察此事件的对象,使观察者做出对应的动作。通常是通过调用各观察者所提供的方法来实现。
观察者模式
CObserver类,为观察者抽象类,为具体观察者定义标准接口:
CSubject类,为主题抽象类,主要为具体的主题类定义标准的接口。主要接口:
CRadio类,具体的主题类(CSubject子类)。例:无线电。
**CInterphone、CPhone **类,具体的观察者类。例:对讲机、手机
如上场景,现某处无线电在特定频道发出广播,所有关注此频道设备都会接收到此信号。
具体主题为Radio,其内部需要在主题发布时,通知所有观察者
class CRadio : public CSubject
{
public:
CRadio()
{
mObserverList.clear();
}
~CRadio()
{
}
int Register(CObserver *pObsr)
{
if (nullptr != pObsr) {
mObserverList.push_back(pObsr);
} else {
OBSERVER_LOGE("Register failed!\n");
return -1;
}
return 0;
}
int Unregister(CObserver *pObsr)
{
if (nullptr != pObsr) {
mObserverList.remove(pObsr);
} else {
OBSERVER_LOGE("Unregister failed!\n");
return -1;
}
return 0;
}
int Notify(void *pMsg)
{
list<CObserver *>::iterator it;
SMsgTransfer *pGmsg = (SMsgTransfer *)pMsg;
OBSERVER_LOG("Send radio: [0x%x] [%s]\n", pGmsg->type, pGmsg->buf);
// loop: 向监听此事件的所有观察者发布主题
for (it = mObserverList.begin(); it != mObserverList.end(); it++) {
(*it)->Update(pMsg);
}
return 0;
}
private:
list <CObserver *> mObserverList;
};
具体观察者为可接收到此无线电的设备:手机、对讲机
/* 监听无线电的设备: 对讲机 */
class CInterphone : public CObserver
{
public:
explicit CInterphone(string value)
{
mName = value;
}
~CInterphone()
{
}
string GetName()
{
return mName;
}
int Update(void *pMsg)
{
SMsgTransfer *msg = (SMsgTransfer *)pMsg;
OBSERVER_LOG("%s receive: [0x%x] [%s]\n", mName.c_str(), msg->type, msg->buf);
return 0;
}
private:
string mName;
};
/* 监听无线电的设备: 手机 */
class CPhone : public CObserver
{
public:
explicit CPhone(string value)
{
mName = value;
}
~CPhone()
{
}
string GetName()
{
return mName;
}
int Update(void *pMsg)
{
if (pMsg != NULL)
{
SMsgTransfer *msg = (SMsgTransfer *)pMsg;
OBSERVER_LOG("%s receive: [0x%x] [%s]\n", mName.c_str(), msg->type, msg->buf);
} else {
OBSERVER_LOG("%s receive messages cannot be resolved!\n", mName.c_str());
}
return 0;
}
private:
string mName;
};
客户端代码。使用Radio和设备形成应用场景
CRadio theRadio;
CPhone thePhoneUser1("Phone user1");
CPhone thePhoneUser2("Phone user2");
CInterphone theInterUser1("Interphone user1");
static int init()
{
// 注册监听无线电的设备,可放在观察者类初始化内部
theRadio.Register(&theInterUser1);
theRadio.Register(&thePhoneUser1);
theRadio.Register(&thePhoneUser2);
return 0;
}
int main(int argc, char *argv[])
{
init();
// 发出SOS无线电
OBSERVER_LOG("------------------------------------------\n");
SMsgTransfer msg1 = {191519, "SOS"};
theRadio.Notify(&msg1);
OBSERVER_LOG("------------------------------------------\n");
SMsgTransfer msg2 = {131313, "HELLO"};
theRadio.Notify(&msg2);
return 0;
}
输出:
$ ./a.out
------------------------------------------
Send radio: [0x2ec1f] [SOS]
Interphone user1 receive: [0x2ec1f] [SOS]
Phone user1 receive: [0x2ec1f] [SOS]
Phone user2 receive: [0x2ec1f] [SOS]
------------------------------------------
Send radio: [0x200f1] [HELLO]
Interphone user1 receive: [0x200f1] [HELLO]
Phone user1 receive: [0x200f1] [HELLO]
Phone user2 receive: [0x200f1] [HELLO]