说起观察者模式犹如黄河之水,滔滔不绝,一发而不可收拾啊。
今天先写上半部分,明天写事件委托。
直接上代码,感谢scl的分享
- // 观察者模式定义了一种一对多的依赖,让多个观察者对象同时监听某一个
- // 主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使
- // 他们能够自动更新自己。
- // 观察者模式是一个很重要的模式,使用频率是非常高啊
- // 当一个对象改变需要同时改变其他对象的时候
- // 当具体不知道有多少个对象有待改变的时候。
- // 适用的范围
- // 在《大话模式》中,众多的观察者对象是上班开小差,看NBA,炒股票的同事
- // 主题对象是坐在门口的前台。当老板回到公司的时候,前台会通知所有的“注册”
- // 后的同事赶紧干正经事。
- // 其实三维浏览中也可以用到
- // 将各种行为作为观察者对象,摄像机为主题对象,主题对象通过给观察对象当前的
- // 时间来更新各种浏览控制器,浏览控制器再调整摄像机各个参数。
- // 情景假设
- // 对一飞机飞行进行控制,
- // 先飞行小于10秒
- // 在旋转小于20秒
- #include "stdafx.h"
- #include <Windows.h>
- #include <iostream>
- #include <vector>
- // 毕竟作为示例,还是开发效率重要,
- // 所以就用using namespace吧
- using namespace std;
- //浏览控制器基类
- class IControl
- {
- public:
- virtual bool Update(double dtime) = 0;
- virtual bool Begin(double dtime ) = 0;
- virtual bool IsFinish() = 0;
- protected:
- double m_dLastTime;
- bool m_bFinish;
- private:
- };
- //飞行浏览控制器
- class FlyControl : public IControl
- {
- public:
- bool Begin(double dtime)
- {
- m_bFinish = false;
- m_dLastTime = dtime;
- return true;
- }
- bool Update(double dtime)
- {
- double dDetal = dtime - m_dLastTime;
- if (dDetal > 10)
- {
- cout<<"Complete fly!"<<endl;
- m_bFinish = true;
- return true;
- }
- cout<<"We have fly "<<dDetal<<" meters!"<<endl;
- }
- bool IsFinish()
- {
- return m_bFinish;
- }
- protected:
- private:
- };
- //转向浏览控制器
- class RotateControl : public IControl
- {
- public:
- bool Begin(double dtime)
- {
- m_bFinish = false;
- m_dLastTime = dtime;
- return true;
- }
- bool Update(double dtime)
- {
- double dDetal = dtime - m_dLastTime;
- if (dDetal > 20)
- {
- cout<<"Complete Rotate!"<<endl;
- m_bFinish = true;
- return true;
- }
- cout<<"We have Rotate "<<dDetal<<" degress"<<endl;
- }
- bool IsFinish()
- {
- return m_bFinish;
- }
- protected:
- private:
- };
- // 控制器集合
- class ControlList
- {
- public:
- int GetCount()
- {
- return m_CtrlVec.size();
- }
- void SetTime(double dTime)
- {
- m_dLastTime = dTime;
- }
- void Attach(IControl *pCtrl)
- {
- for (int i = 0; i < m_CtrlVec.size(); i++)
- {
- if (pCtrl == m_CtrlVec[i])
- {
- return;
- }
- }
- m_CtrlVec.push_back(pCtrl);
- }
- void Detach(IControl *pCtrl)
- {
- for (int i = 0; i < m_CtrlVec.size(); i ++)
- {
- if (pCtrl == m_CtrlVec[i])
- {
- m_CtrlVec.erase(m_CtrlVec.begin() + i);
- }
- return;
- }
- }
- bool UpdateAllCtrls(double dtime)
- {
- double dT = dtime - m_dLastTime;
- if (dT == 0.0)
- {
- return false;
- }
- int nSize = m_CtrlVec.size();
- if ( m_CtrlVec.size() != 0 )
- {
- IControl* pCtrl = m_CtrlVec.front();
- if ( NULL != pCtrl )
- {
- pCtrl->Update( dtime );
- if ( pCtrl->IsFinish() )
- {
- delete pCtrl;
- pCtrl = NULL;
- m_CtrlVec.erase(m_CtrlVec.begin());
- if ( m_CtrlVec.size() != 0 )
- {
- pCtrl = m_CtrlVec.front();
- if ( NULL != pCtrl )
- {
- pCtrl->Begin( dtime );
- }
- }
- }
- }
- }
- m_dLastTime = dtime;
- return true;
- }
- protected:
- private:
- std::vector<IControl*> m_CtrlVec;
- double m_dLastTime;
- };
- //
- // Plain
- // 飞机类
- class Plain : public ControlList
- {
- public:
- protected:
- private:
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- //演示程序,就不用多线程了
- Plain plain;
- //恩,现在时刻是0.0
- double curTime = 0.0;
- plain.SetTime(curTime);
- FlyControl *pFlyCtrl = new FlyControl;
- pFlyCtrl->Begin(curTime);
- plain.Attach(pFlyCtrl);
- //恩,现在时刻是0.1
- curTime = 0.1;
- RotateControl *pRoCtrl = new RotateControl;
- pRoCtrl->Begin(curTime);
- plain.Attach(pRoCtrl);
- while(plain.GetCount())
- {
- Sleep(200);
- // 模拟时间的流逝
- // 7.5倍的速度
- curTime += 1.5;
- plain.UpdateAllCtrls(curTime);
- }
- return 0;
- }
- // 输出结果
- //We have fly 1.6 meters!
- //We have fly 3.1 meters!
- //We have fly 4.6 meters!
- //We have fly 6.1 meters!
- //We have fly 7.6 meters!
- //We have fly 9.1 meters!
- //Complete fly!
- //We have Rotate 1.5 degress
- //We have Rotate 3 degress
- //We have Rotate 4.5 degress
- //We have Rotate 6 degress
- //We have Rotate 7.5 degress
- //We have Rotate 9 degress
- //We have Rotate 10.5 degress
- //We have Rotate 12 degress
- //We have Rotate 13.5 degress
- //We have Rotate 15 degress
- //We have Rotate 16.5 degress
- //We have Rotate 18 degress
- //We have Rotate 19.5 degress
- //Complete Rotate!
- //请按任意键继续. . .
恩,这部分就是单纯的委托了
直接贴代码
- // 委托就是i一种引用方法的类型,一旦为委托分配了方法,委托将与
- // 该方法具有完全相同的行为,委托方法的使用可以像其他任何方法一样,
- // 具有参数和返回值,委托可以看做是对函数的抽象,是函数的“类”,委托
- // 的实例代表一个具体的函数
- // 委托对象所搭载的所有方法必须具有相同的原型和相识,
- // 也就是有相同的参数列表和返回值类型
- // C++ 函数指针很神奇,不是吗?
- #include "stdafx.h"
- #include <Windows.h>
- #include <iostream>
- #include <vector>
- using namespace std;
- // 对象类,也可以使用类模板来实现
- // 实际上,对于void* pArg可以进行进一步的封装
- class Object
- {
- public:
- typedef long (Object::*pFunc)(Object *pObj, void* pArg);
- protected:
- private:
- };
- class NameContainer
- {
- public:
- string strName;
- };
- // 事件类
- class EventHandler
- {
- public:
- EventHandler(Object *pObject, Object::pFunc pFuncion)
- : m_pObj(pObject)
- , m_pFunc(pFuncion)
- {
- }
- long operator()(Object* pObj, void* pArg)
- {
- return (m_pObj->*m_pFunc)(pObj, pArg);
- }
- protected:
- Object *m_pObj;
- Object::pFunc m_pFunc;
- private:
- };
- // 事件类的容器
- class EventsContainer
- {
- public:
- // 某些重载就不写了
- EventsContainer& operator +=(const EventHandler& rEvent)
- {
- m_EventsVec.push_back(rEvent);
- return *this;
- }
- long operator()(Object* pObj, void *pArg)
- {
- for (int i = 0; i < m_EventsVec.size(); i ++)
- {
- // 暂不对返回值进行判断
- m_EventsVec[i](pObj, pArg);
- }
- return 0;
- }
- protected:
- private:
- vector<EventHandler> m_EventsVec;
- };
- class PersonA : public Object
- {
- public:
- PersonA(const string &strName)
- {
- m_strName = strName;
- }
- long TellName(Object *pObj, void* pArg)
- {
- // 当然,PersonA是知道这个函数是干什么的,参数是什么
- // 如果不知道的话,利用多态也可以很好解决问题
- // 大不了就是抽象出参数部分处理函数
- string strName = (*((NameContainer*)pArg)).strName;
- cout<<"Hello! "<<strName.c_str()<<".\nMy name is: "<<m_strName.c_str()<<endl;
- // 直接cout pArg 就是这个指针的地址了
- return 1;
- }
- protected:
- private:
- string m_strName;
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- EventsContainer tellName;
- PersonA *pA = new PersonA("Joky");
- // Joky不是一个敏锐的人,所以他每次参加聚会前都带着一个提示器
- // 以便于第一时间做自我介绍,尤其是对美女
- // 提示器是[tellName]系统
- //注册事件
- tellName += EventHandler(
- (Object*)pA, // 主体
- (Object::pFunc)&PersonA::TellName); // 事件
- // 在一次聚会上
- // Joky通过[tellName}系统获得了一个陌生人的名字
- // 陌生人叫[Fuuny]
- NameContainer nc;
- nc.strName = "Fuuny";
- tellName(pA, (void*)&nc);
- if (pA)
- {
- delete pA;
- pA = NULL;
- }
- return 0;
- }
- // 执行结果
- //Hello! Fuuny.
- //My name is: Joky
- //请按任意键继续. . .