Observer Pattern:定义了对象之间的一对多的依赖,这样一来,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新。
类似的思想在游戏中体现很多,比如OGRE中的Listener(监听者)和Hooker(钩子),都是通过注册或者绑定到一个状态体上,当状态体的关注数据变化回调这个“观察者“。OO编程的一个重要原则就是松耦合的使用,这样可以使程序更加的又弹性,更能应对变化。观察者模式就是一个典型的松耦合,观察者和主题分别只暴露了非常少的接口,双方对于彼此可以说完全不知道对方的内部实现,只调用接口就可以。
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
关键字:一对多,注册,注销,通知,松耦合
上面实现了一个简单的游戏对象属性变化时的观察者调用,下面的代码用来简单的测试:
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;
}