观察者模式——Observer

说起观察者模式犹如黄河之水,滔滔不绝,一发而不可收拾啊。

今天先写上半部分,明天写事件委托。




直接上代码,感谢scl的分享


[cpp]  view plain copy
  1. // 观察者模式定义了一种一对多的依赖,让多个观察者对象同时监听某一个  
  2.  // 主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使  
  3.  // 他们能够自动更新自己。  
  4.    
  5.    
  6.    
  7.  // 观察者模式是一个很重要的模式,使用频率是非常高啊  
  8.    
  9.  // 当一个对象改变需要同时改变其他对象的时候  
  10.  // 当具体不知道有多少个对象有待改变的时候。  
  11.    
  12.    
  13.  // 适用的范围  
  14.  // 在《大话模式》中,众多的观察者对象是上班开小差,看NBA,炒股票的同事  
  15.  // 主题对象是坐在门口的前台。当老板回到公司的时候,前台会通知所有的“注册”  
  16.  // 后的同事赶紧干正经事。  
  17.    
  18.    
  19.  // 其实三维浏览中也可以用到  
  20.  // 将各种行为作为观察者对象,摄像机为主题对象,主题对象通过给观察对象当前的  
  21.  // 时间来更新各种浏览控制器,浏览控制器再调整摄像机各个参数。  
  22.    
  23.    
  24.    
  25.  // 情景假设  
  26.  // 对一飞机飞行进行控制,  
  27.  // 先飞行小于10秒  
  28.  // 在旋转小于20秒  
  29.    
  30.    
  31.    
  32.  #include "stdafx.h"  
  33.  #include <Windows.h>  
  34.  #include <iostream>  
  35.  #include <vector>  
  36.    
  37.  // 毕竟作为示例,还是开发效率重要,  
  38.  // 所以就用using namespace吧  
  39.  using namespace std;  
  40.    
  41.  //浏览控制器基类  
  42.  class IControl  
  43.  {  
  44.  public:  
  45.  virtual bool Update(double dtime) = 0;  
  46.  virtual bool Begin(double dtime ) = 0;  
  47.  virtual bool IsFinish() = 0;  
  48.    
  49.  protected:  
  50.     double  m_dLastTime;  
  51.     bool    m_bFinish;  
  52.  private:  
  53.  };  
  54.    
  55.  //飞行浏览控制器  
  56.  class FlyControl : public IControl  
  57.  {  
  58.  public:  
  59.     bool Begin(double dtime)  
  60.     {  
  61.         m_bFinish = false;  
  62.         m_dLastTime = dtime;  
  63.         return true;  
  64.     }  
  65.     bool Update(double dtime)  
  66.     {  
  67.         double dDetal = dtime - m_dLastTime;  
  68.         if (dDetal > 10)  
  69.         {  
  70.             cout<<"Complete fly!"<<endl;  
  71.             m_bFinish = true;  
  72.             return true;  
  73.         }  
  74.         cout<<"We have fly  "<<dDetal<<"  meters!"<<endl;  
  75.     }  
  76.     bool IsFinish()  
  77.     {  
  78.         return m_bFinish;  
  79.     }  
  80.  protected:  
  81.  private:  
  82.  };  
  83.    
  84.  //转向浏览控制器  
  85.  class RotateControl : public IControl  
  86.  {  
  87.  public:  
  88.     bool Begin(double dtime)  
  89.     {  
  90.         m_bFinish = false;  
  91.         m_dLastTime = dtime;  
  92.         return true;  
  93.     }  
  94.     bool Update(double dtime)  
  95.     {  
  96.         double dDetal = dtime - m_dLastTime;  
  97.         if (dDetal > 20)  
  98.         {  
  99.             cout<<"Complete Rotate!"<<endl;  
  100.             m_bFinish = true;  
  101.             return true;  
  102.         }  
  103.         cout<<"We have Rotate  "<<dDetal<<"  degress"<<endl;  
  104.     }  
  105.     bool IsFinish()  
  106.     {  
  107.         return m_bFinish;  
  108.     }  
  109.  protected:  
  110.  private:  
  111.  };  
  112.    
  113.    
  114.  // 控制器集合  
  115.  class ControlList  
  116.  {  
  117.  public:  
  118.     int GetCount()  
  119.     {  
  120.         return m_CtrlVec.size();  
  121.     }  
  122.     void SetTime(double dTime)  
  123.     {  
  124.         m_dLastTime = dTime;  
  125.     }  
  126.     void Attach(IControl *pCtrl)  
  127.     {  
  128.         for (int i = 0; i < m_CtrlVec.size(); i++)  
  129.         {  
  130.             if (pCtrl == m_CtrlVec[i])  
  131.             {  
  132.                 return;  
  133.             }  
  134.         }  
  135.         m_CtrlVec.push_back(pCtrl);  
  136.     }  
  137.     void Detach(IControl *pCtrl)  
  138.     {  
  139.         for (int i = 0; i < m_CtrlVec.size(); i ++)  
  140.         {  
  141.             if (pCtrl == m_CtrlVec[i])  
  142.             {  
  143.                 m_CtrlVec.erase(m_CtrlVec.begin() + i);  
  144.             }  
  145.             return;  
  146.         }  
  147.     }  
  148.    
  149.     bool UpdateAllCtrls(double dtime)  
  150.     {  
  151.         double dT = dtime - m_dLastTime;  
  152.         if (dT == 0.0)  
  153.         {  
  154.             return false;  
  155.         }  
  156.    
  157.         int nSize = m_CtrlVec.size();  
  158.         if ( m_CtrlVec.size() != 0 )   
  159.         {     
  160.             IControl* pCtrl = m_CtrlVec.front();  
  161.             if ( NULL != pCtrl )   
  162.             {  
  163.                 pCtrl->Update( dtime );  
  164.    
  165.                 if ( pCtrl->IsFinish() )   
  166.                 {  
  167.                     delete pCtrl;  
  168.                     pCtrl = NULL;  
  169.                     m_CtrlVec.erase(m_CtrlVec.begin());  
  170.    
  171.                     if ( m_CtrlVec.size() != 0 )   
  172.                     {  
  173.                         pCtrl = m_CtrlVec.front();  
  174.                         if ( NULL != pCtrl )   
  175.                         {  
  176.                             pCtrl->Begin( dtime );  
  177.                         }                                 
  178.                     }   
  179.                 }   
  180.             }   
  181.         }   
  182.    
  183.         m_dLastTime = dtime;  
  184.    
  185.         return true;  
  186.     }  
  187.    
  188.  protected:  
  189.  private:  
  190.     std::vector<IControl*>    m_CtrlVec;  
  191.     double                  m_dLastTime;  
  192.    
  193.  };  
  194.    
  195.    
  196.  //   
  197.  // Plain  
  198.  // 飞机类  
  199.  class Plain : public ControlList  
  200.  {  
  201.  public:  
  202.  protected:  
  203.  private:  
  204.  };  
  205.    
  206.    
  207.  int _tmain(int argc, _TCHAR* argv[])  
  208.  {  
  209.     //演示程序,就不用多线程了  
  210.    
  211.     Plain plain;  
  212.       
  213.     //恩,现在时刻是0.0  
  214.     double curTime = 0.0;  
  215.     plain.SetTime(curTime);  
  216.     FlyControl *pFlyCtrl = new FlyControl;  
  217.     pFlyCtrl->Begin(curTime);  
  218.     plain.Attach(pFlyCtrl);  
  219.     //恩,现在时刻是0.1  
  220.     curTime = 0.1;   
  221.     RotateControl *pRoCtrl = new RotateControl;  
  222.     pRoCtrl->Begin(curTime);  
  223.     plain.Attach(pRoCtrl);  
  224.    
  225.     while(plain.GetCount())  
  226.     {  
  227.         Sleep(200);  
  228.         // 模拟时间的流逝  
  229.         // 7.5倍的速度  
  230.         curTime += 1.5;  
  231.         plain.UpdateAllCtrls(curTime);  
  232.     }  
  233.    
  234.     return 0;  
  235.  }  
  236.    
  237.  // 输出结果  
  238.  //We have fly  1.6  meters!  
  239.  //We have fly  3.1  meters!  
  240.  //We have fly  4.6  meters!  
  241.  //We have fly  6.1  meters!  
  242.  //We have fly  7.6  meters!  
  243.  //We have fly  9.1  meters!  
  244.  //Complete fly!  
  245.  //We have Rotate  1.5  degress  
  246.  //We have Rotate  3  degress  
  247.  //We have Rotate  4.5  degress  
  248.  //We have Rotate  6  degress  
  249.  //We have Rotate  7.5  degress  
  250.  //We have Rotate  9  degress  
  251.  //We have Rotate  10.5  degress  
  252.  //We have Rotate  12  degress  
  253.  //We have Rotate  13.5  degress  
  254.  //We have Rotate  15  degress  
  255.  //We have Rotate  16.5  degress  
  256.  //We have Rotate  18  degress  
  257.  //We have Rotate  19.5  degress  
  258.  //Complete Rotate!  
  259.  //请按任意键继续. . .  

恩,这部分就是单纯的委托了

直接贴代码

[cpp]  view plain copy
  1. // 委托就是i一种引用方法的类型,一旦为委托分配了方法,委托将与  
  2.  // 该方法具有完全相同的行为,委托方法的使用可以像其他任何方法一样,  
  3.  // 具有参数和返回值,委托可以看做是对函数的抽象,是函数的“类”,委托  
  4.  // 的实例代表一个具体的函数  
  5.    
  6.  // 委托对象所搭载的所有方法必须具有相同的原型和相识,  
  7.  // 也就是有相同的参数列表和返回值类型  
  8.    
  9.    
  10.  // C++ 函数指针很神奇,不是吗?  
  11.    
  12.  #include "stdafx.h"  
  13.  #include <Windows.h>  
  14.  #include <iostream>  
  15.  #include <vector>  
  16.  using namespace std;  
  17.    
  18.  // 对象类,也可以使用类模板来实现  
  19.  // 实际上,对于void* pArg可以进行进一步的封装  
  20.  class Object  
  21.  {  
  22.  public:  
  23.     typedef long (Object::*pFunc)(Object *pObj, void* pArg);  
  24.  protected:  
  25.  private:  
  26.  };  
  27.    
  28.    
  29.  class NameContainer  
  30.  {  
  31.  public:  
  32.     string strName;  
  33.  };  
  34.    
  35.  // 事件类  
  36.  class EventHandler  
  37.  {  
  38.  public:  
  39.     EventHandler(Object *pObject, Object::pFunc pFuncion)  
  40.         : m_pObj(pObject)  
  41.         , m_pFunc(pFuncion)  
  42.     {  
  43.    
  44.     }  
  45.    
  46.     long operator()(Object* pObj, void* pArg)  
  47.     {  
  48.         return (m_pObj->*m_pFunc)(pObj, pArg);  
  49.     }  
  50.  protected:  
  51.     Object          *m_pObj;  
  52.     Object::pFunc   m_pFunc;  
  53.  private:  
  54.  };  
  55.    
  56.  // 事件类的容器  
  57.  class EventsContainer  
  58.  {  
  59.  public:  
  60.     // 某些重载就不写了  
  61.     EventsContainer& operator +=(const EventHandler& rEvent)  
  62.     {  
  63.         m_EventsVec.push_back(rEvent);  
  64.         return *this;  
  65.     }  
  66.     long operator()(Object* pObj, void *pArg)  
  67.     {  
  68.         for (int i = 0; i < m_EventsVec.size(); i ++)  
  69.         {  
  70.             // 暂不对返回值进行判断  
  71.             m_EventsVec[i](pObj, pArg);  
  72.         }  
  73.         return 0;  
  74.     }  
  75.  protected:  
  76.    
  77.  private:  
  78.     vector<EventHandler>  m_EventsVec;  
  79.  };  
  80.    
  81.    
  82.    
  83.  class PersonA : public Object  
  84.  {  
  85.  public:  
  86.     PersonA(const string &strName)  
  87.     {  
  88.         m_strName = strName;  
  89.     }  
  90.     long TellName(Object *pObj, void* pArg)  
  91.     {  
  92.           
  93.         // 当然,PersonA是知道这个函数是干什么的,参数是什么  
  94.         // 如果不知道的话,利用多态也可以很好解决问题  
  95.         // 大不了就是抽象出参数部分处理函数  
  96.         string strName = (*((NameContainer*)pArg)).strName;  
  97.           
  98.         cout<<"Hello! "<<strName.c_str()<<".\nMy name is: "<<m_strName.c_str()<<endl;  
  99.         // 直接cout pArg 就是这个指针的地址了  
  100.         return 1;  
  101.     }  
  102.  protected:  
  103.  private:  
  104.     string m_strName;  
  105.  };  
  106.    
  107.  int _tmain(int argc, _TCHAR* argv[])  
  108.  {  
  109.     EventsContainer  tellName;  
  110.     PersonA *pA = new PersonA("Joky");  
  111.     // Joky不是一个敏锐的人,所以他每次参加聚会前都带着一个提示器  
  112.     // 以便于第一时间做自我介绍,尤其是对美女  
  113.     // 提示器是[tellName]系统  
  114.     //注册事件  
  115.     tellName += EventHandler(  
  116.                             (Object*)pA,                         // 主体   
  117.                             (Object::pFunc)&PersonA::TellName);  // 事件  
  118.    
  119.     // 在一次聚会上  
  120.     // Joky通过[tellName}系统获得了一个陌生人的名字  
  121.     // 陌生人叫[Fuuny]  
  122.     NameContainer nc;  
  123.     nc.strName = "Fuuny";  
  124.     tellName(pA, (void*)&nc);  
  125.    
  126.     if (pA)  
  127.     {  
  128.         delete pA;  
  129.         pA = NULL;  
  130.     }  
  131.    
  132.     return 0;  
  133.  }  
  134.    
  135.    
  136.  // 执行结果  
  137.  //Hello! Fuuny.  
  138.  //My name is: Joky  
  139.  //请按任意键继续. . .  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值