Observer Pattern:定义了对象之间的一对多的依赖,这样一来,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新。
类似的思想在游戏中体现很多,比如OGRE中的Listener(监听者)和Hooker(钩子),都是通过注册或者绑定到一个状态体上,当状态体的关注数据变化回调这个“观察者“。OO编程的一个重要原则就是松耦合的使用,这样可以使程序更加的又弹性,更能应对变化。观察者模式就是一个典型的松耦合,观察者和主题分别只暴露了非常少的接口,双方对于彼此可以说完全不知道对方的内部实现,只调用接口就可以。
/** @ Class: IObserver(观察者接口类) */ class IObserver { public: virtual ~IObserver() {}; public: virtual void Update( ISubject* pSubject ) = 0; }; /** @ Class: IOutput(信息输出接口类) */ class IOutput { public: virtual ~IOutput() {}; public: virtual void Output( const char* pInfo ) { cout << pInfo << endl; } }; /** @ Class: HpObserver(血气观察者) */ class HpObserver : public IObserver, public IOutput { public: HpObserver() {}; ~HpObserver() {}; public: void Update( ISubject* pSubject ) { long hp = pSubject->GetProperty( "Hp" ); char szBuffer[32]; sprintf( szBuffer, "HpObserver Report: HP = %d", hp ); Output( szBuffer ); } }; /** @ Class: MpObserver(魔法观察者) */ class MpObserver : public IObserver, public IOutput { public: MpObserver() {}; ~MpObserver() {}; public: void Update( ISubject* pSubject ) { long mp = pSubject->GetProperty( "Mp" ); char szBuffer[32]; sprintf( szBuffer, "HpObserver Report: Mp = %d", mp ); Output( szBuffer ); } }; /** @ Class: ISubject(主题基础类) */ class IObserver; class ISubject { public: ISubject() : m_bChanged( true ) {}; virtual ~ISubject() {}; public: virtual void RegisterObserver( IObserver* pObserver ) = 0; virtual void RemoveObserver( IObserver* pObserver ) = 0; virtual void NotifyObserver( ISubject* pSubject ) = 0; virtual long GetProperty( const char* type ) = 0; void RefreshProperty() { NotifyObserver( this ); } void SetChange( bool bChange ){ m_bChanged = bChange; } bool GetChange( void ) { return m_bChanged; } protected: bool m_bChanged; }; /** @ Class: RoleSubject(主角主题类) */ class RoleSubject : public ISubject { public: RoleSubject() {}; ~RoleSubject() { m_VctObserver.clear(); }; public: void RegisterObserver( IObserver* pObserver ) { for( int nIndex = 0; nIndex < m_VctObserver.size(); ++nIndex ) { IObserver* pObs = m_VctObserver[nIndex]; if( pObs == pObserver ) return; } m_VctObserver.push_back( pObserver ); } void RemoveObserver( IObserver* pObserver ) { for( int nIndex = 0; nIndex < m_VctObserver.size(); ++nIndex ) { IObserver* pObs = m_VctObserver[nIndex]; if( pObs == pObserver ) { m_VctObserver.erase( m_VctObserver.begin() + nIndex ); return; } } } void NotifyObserver( ISubject* pSubject ) { if( m_bChanged == false ) return; for( int nIndex = 0; nIndex < m_VctObserver.size(); ++nIndex ) { IObserver* pObs = m_VctObserver[nIndex]; if( pObs ) pObs->Update( pSubject ); } } long GetProperty( const char* type ) { return 10; // 测试而已 } private: vector<IObserver*> m_VctObserver; };
输入的结果如下:
1th Change:
HpObserver Report: HP = 10
HpObserver Report: Mp = 10
2nd Change:
HpObserver Report: Mp = 10
关键字:一对多,注册,注销,通知,松耦合
上面实现了一个简单的游戏对象属性变化时的观察者调用,下面的代码用来简单的测试:
int main() { IObserver* pObserver1 = new HpObserver(); IObserver* pObserver2 = new MpObserver(); ISubject* pSubject = new RoleSubject(); pSubject->RegisterObserver( pObserver1 ); pSubject->RegisterObserver( pObserver2 ); cout << "1th Change:" << endl; pSubject->RefreshProperty(); pSubject->RemoveObserver( pObserver1 ); cout << "2nd Change:" << endl; pSubject->RefreshProperty(); pSubject->RemoveObserver( pObserver2 ); delete pObserver1; delete pObserver2; delete pSubject; return 0; }