有一次我實現了一個狀態機這樣的:有什麼辦法可以調用模板參數類的未知方法嗎?
class Player
{
public:
int Run();
int Jump();
int Stop();
private:
class State
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};
class StandingState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};
class RunningState : public State
{
virtual int Run() { /*...*/ }
virtual int Jump() { /*...*/ }
virtual int Stop() { /*...*/ }
};
// More states go here!
std::list<State*> states;
State* currentState;
};
int Player::Run()
{
int result = m_currentState->Run();
// do something with result
}
int Player::Jump()
{
int result = m_currentState->Jump();
// do something with result
}
int Player::Stop()
{
int result = m_currentState->Stop();
// do something with result
}
相當教材我認爲:Player
代表從外部調用當前State
對象,並做一些事情,結果(可能轉換爲其他狀態)。實質上,每個狀態都知道給定的動作如何影響它,但是狀態機需要將各種狀態連接在一起。我發現這是一個很好的問題分離。
但我看到了這裏的抽象的可能性。整個系統由State
類的接口定義:
- 兩個狀態機和所述子狀態實施
State
- 該狀態機保持一個指針,指向所有可能
State
s,並且當前State
- 無論的
State
方法被稱爲狀態機,它被undiscerningly轉發到當前狀態。
所以,我們完全可以使這個類模板,對不對?看:
template< class StateInterface >
class StateMachine : public StateInterface
{
// public methods already declared in StateInterface
protected:
std::list<StateInterface*> states;
void AddState(StateInterface* state);
StateInterface* currentState;
};
class PlayerStateInterface
{
public:
virtual int Run() = 0;
virtual int Jump() = 0;
virtual int Stop() = 0;
};
class Player : public StateMachine<PlayerStateInterface>
{
public:
virtual int Run() { currentState->Run(); /* do stuff */ }
virtual int Jump() { currentState->Jump(); /* do stuff */ }
virtual int Stop() { currentState->Stop(); /* do stuff */ }
};
以上幾點,這有1和2覆蓋,但3呢?我仍然需要手動將調用委託給具體狀態機實現中的當前狀態。有沒有辦法將該功能移至StateMachine
模板?我能以某種方式表達每當StateInterface
一個方法被調用StateMachine
應該呼籲currentState
同樣的方法,當我不知道StateInterface
的方法的名稱或簽名?
你可能會有興趣看看[STTCL(http://makulik.github.io/sttcl/) - 我用正是原理設計而成。 (對不起一些缺點:接口方法(事件),需要由頂層和子狀態機是已知的) –
我想'StandingState'和'RunningState'從'State'推導第一碼塊? – dyp
@DyP:Bloops!很對,編輯。謝謝。 – suszterpatt