前言
之前 观察者模式一篇 中,【通知者】需要知道【观察者】的类名和更新函数名,耦合度稍大,本篇稍稍修改一下,类似于大话设计模式里的C#描述的委托事件的方法。
采用 将类成员函数指针转换为普通指针 的方式,把每个【观察者】类的 相同原型的更新函数 指针转换为std::function然后保存起来。
然后在【通知者】的 通知函数 中调用保存起来的每个 【观察者】的更新函数。
本文去除了【观察者】的继承结构,【通知者】只需要知道每个【观察者】的更新函数原型。
去除了继承结构,因此每个【观察者】的更新函数也就不必是virtual的了。
描述
/************************************************************************/
/* 设计模式 观察者模式 本文介绍一种解耦的方法,使【通知者】不依赖于【观察者】 即【通知者】不知道【观察者】的太多细节,只需要知道【观察者】 的【更新函数原型】,所以这就要求【观察者】的更新函数的原型 要一致。 以【大话设计模式】里的讲到的Visual Studio的窗口变化为例: 当【启动调试】时,【输出】窗口展开,【反汇编】窗口展开 当【结束调试】时,【输出】窗口隐藏,【反汇编】窗口隐藏 所以这里的【通知者】为【调试器】,【观察者】为【输出】和【反汇编】窗口 /************************************************************************/
//调试器的两个行为:启动 和 停止
typedef enum _ESubjectState{Start = 0, End = 1}ESubjectState;
所需头文件
#include "stdafx.h" #include <iostream> #include <algorithm> #include <vector> #include <map> #include <functional>
using namespace std;
PS:
说到头文件,不得不PS一下下,看头文件里的map,由于在用vector保存std::function时,不能使用std::find函数,也不能在for(iter)中使用if(*iter == std::function XX),因此我试图使用map来保证保存std::functiond唯一性,用map的find来查找待删除的观察者的更新函数。
是试图!!! 经过测试,发现还是不行!
在VC群里HB说因为std::function没有operator ==, 因此不能使用std::find函数, 因此也不能if(*iter == std::function XX),我想map可能是同样的原因。
两个观察者
观察者1:输出窗口类
//【观察者】--【输出窗口类】
class COutputWnd { public: COutputWnd(); virtual ~COutputWnd(); void UpdateOutWnd(ESubjectState e); //更新状态
}; COutputWnd::COutputWnd(){} COutputWnd::~COutputWnd(){} void COutputWnd::UpdateOutWnd(ESubjectState e) { switch(e) { case Start: cout<<"调试器启动了,展开 输出窗口 \n"; break; case End: cout<<"调试器关闭了,收起 输出窗口 \n"; default: break; } }
观察者2:反汇编窗口类
//【观察者】--【反汇编窗口类】
class CDisassembling
{ public: CDisassembling(); virtual ~CDisassembling(); void UpdateDisassembling(ESubjectState e); }; CDisassembling::CDisassembling(){} CDisassembling::~CDisassembling(){} void CDisassembling::UpdateDisassembling(ESubjectState e) { switch(e) { case Start: cout<<"调试器启动了,展开 反汇编窗口 \n"; break; case End: cout<<"调试器关闭了,收起 反汇编窗口 \n"; break; default: break; } }
通知者类
通知者抽象基类
//【通知者】抽象类
class CSubject { public: typedef std::function<void(ESubjectState)> PUpdateFunc; typedef vector<PUpdateFunc> PTRVEC; CSubject(); virtual ~CSubject(); virtual void AddObserer(PUpdateFunc pFunc) = 0; //添加观察者
virtual void RemoveObserver(PUpdateFunc pFunc) = 0; //删除观察者
virtual void Notify(ESubjectState e) = 0; //通知函数
protected: PTRVEC m_ptrArr; }; CSubject::CSubject(){} CSubject::~CSubject(){}
具体通知者类:调试器类
/************************************** 和前一篇将的在使用std::function时的问题类似,这里在函数AddObsererstd中使用std::find函数和RemoveObserver函数中使用std::find函数和opeartor == 时都有问题。 即暂时不能判断vector中没有待插入的函数时才插入, 也不能在删除观察者时查找到后再erase ***************************************/
//【通知者】--【调试器类】
class CDebugger : public CSubject { public: CDebugger(); virtual ~CDebugger(); virtual void AddObserer(PUpdateFunc pFunc); //添加观察者
virtual void RemoveObserver(PUpdateFunc pFunc); //删除观察者
virtual void Notify(ESubjectState e); //通知函数
}; CDebugger::CDebugger(){} CDebugger::~CDebugger(){} //添加观察者,当待添加的观察者不存在时才添加
void CDebugger::AddObserer(PUpdateFunc pFunc) { //if(find(m_ptrArr.begin(), m_ptrArr.end(), pFunc) == m_ptrArr.end())
m_ptrArr.push_back(pFunc); } //删除观察者, 暂时不能删除
void CDebugger::RemoveObserver(PUpdateFunc pFunc) { /* PTRVEC::iterator iter = find(m_ptrArr.begin(), m_ptrArr.end(), pFunc); if(m_ptrArr.end() != iter) m_ptrArr.erase(iter);*/
/*for (PTRVEC::iterator iter = m_ptrArr.begin(); iter != m_ptrArr.end(); ++ iter) { } */ } void CDebugger::Notify(ESubjectState e) { for (PTRVEC::iterator iter = m_ptrArr.begin(); iter != m_ptrArr.end(); ++ iter) { (*iter)(e); } }
客户端代码
int _tmain(int argc, _TCHAR* argv[]) { //通知者
CSubject* pSubject = new CDebugger(); //三个观察者, 一个是输出窗口, 另外两个是反汇编窗口
COutputWnd objOutPut; CDisassembling objDisassembling1; CDisassembling objDisassembling2; cout<<"-----------添加三个观察者------------"<<endl; CSubject::PUpdateFunc func1 = std::bind(&COutputWnd::UpdateOutWnd, &objOutPut, std::placeholders::_1); pSubject->AddObserer(func1); CSubject::PUpdateFunc func2 = std::bind(&CDisassembling::UpdateDisassembling, &objDisassembling1, std::placeholders::_1); pSubject->AddObserer(func2); CSubject::PUpdateFunc func3 = std::bind(&CDisassembling::UpdateDisassembling, &objDisassembling2, std::placeholders::_1); pSubject->AddObserer(func3); pSubject->Notify(Start); cout<<endl; pSubject->Notify(End); cout<<endl<<"----------把观察者3删除-------------"<<endl; pSubject->RemoveObserver(func3); pSubject->Notify(Start); cout<<endl; pSubject->Notify(End); cout<<endl<<endl; delete pSubject; pSubject = NULL; return 0; }
运行结果