2013-04-02 33 views
1

我正在爲遊戲編寫一個StateManager(我使用C++和SFML,但我試圖隱藏特定於語言的元素,因爲這是關於任何OOP語言的問題)。 我有一個設置,其中一個StateManager更新當前活動狀態。然而,一個國家必須能夠改變活動狀態(例如,按下菜單中的「播放」開始播放狀態),所以我保持對StateManager中StateManager的引用。避免意大利麪代碼(gamestatemanager)

下面是一個使事情更清晰的UML圖。 UML diagram StateManager

如您所見,StateManager和State都引用了彼此。 如何避免spaghetticode?我應該讓StateManager成爲單身人士嗎?雖然我們認爲,遊戲課應該是單身課程嗎?我可以很容易地做到這一點,但是我並不喜歡我的遊戲中的其他類能夠訪問遊戲類或statemanager類,即使我是唯一的程序員。

+0

你能分出國家需要訪問的部分嗎?即從更簡單的契約(接口)組成StateManager?即可更新和呈現的IRenderable。然後你只給StateManager的這個部分。你也想把這個IRenderable注入狀態(即查看控制反轉)。 –

+0

我不確定你的意思。你能舉出這樣一個例子嗎?你的意思是會有另一個類與changeState方法,該國有這個類的引用,但不是給StateManager? – RaptorDotCpp

回答

1

您需要設計合同也被稱爲接口。例如,一個狀態(原則上)不需要訪問狀態機。雖然狀態的實現可能需要訪問。例如,在C#:

public interface IState 
{ 
    void Render(); 
    void Update(); 
} 

public interface IStateMachine 
{ 
    void ChangeState(IState newState); 
} 

public class MenuState : IState 
{ 
    private IStateMachine _stateMachine; 

    public MenuState(IStateMachine stateMachine) 
    { 
     _stateMachine = stateMachine; 
    } 

    public void Render() 
    { 
    } 

    public void Update() 
    { 
    } 
} 

public class StateMachineImplementation : IStateMachine 
{ 
    public void ChangeState(IState newState) 
    { 
    } 
} 

通知IState任何實現並不知道任何IStateMachine實施的,他們只是在合同的工作。另請注意,MenuState不關心'IStateMachine'來自哪裏(控制反轉),它只是用它。

如果需要,您可以將其他功能添加到IStateMachineGetStates()

最終,您使用這些合約來避免耦合;這意味着你可以完全替代執行IStateManager和(假設遵守合同),MenuState仍然可以正常工作。

+0

如果我有一個隱式契約(我是唯一的程序員,可能不會釋放我的源代碼),說一個StateManager應該有一個ChangeState方法,那也可以嗎?在這種情況下使用**合同**除了清潔設計還有其他好處嗎? – RaptorDotCpp

+1

很多人在評論中提到,但一句話:*解耦*。基本上,你想要它,所以你可以取代合同的執行,它不會破壞任何東西;即「MenuState」與「IStateManager」合約做了什麼,仍然有效。簡而言之,這就是它。 –

1

雙向引用沒有任何問題。查看Qt的QWidgets的父/子模型。如果每個狀態只能影響一個StateManager,則使每個狀態在其構造中採用一個指向StateManager「父」的指針,或者稍後進行設置。 StateManager可以跟蹤其集合中的「子」,並且每個孩子都知道其父母是誰,因此它可以通知該父母任何變化。

編輯: 我認爲首先要看的是打破你的州級。目前它代表了一種狀態和一種改變爲該狀態的行動。行動應該知道一個StateMachine,告訴它改變狀態。國家應該是國家機器的內部。

+0

我認爲它有什麼問題,因爲我們必須爲大學設計一個應用程序,他們告訴我們這是最糟糕的設計。 – RaptorDotCpp

+1

那麼,理想情況下,你會使用某種基於事件的系統,這樣一個國家就可以向全世界尖叫「嘿,我已經改變了一些東西!」,並且一個StateManager知道傾聽這些事件並對它們做出迴應。這樣一個國家就不需要了解國家經理人或外面的世界。它只是說:「嘿,任何關心的人,用戶都希望你現在玩,只是說'。」然後離開它。如果合適的話,由其他班級來聽取並做出迴應。 我想,這超出了你設計的範圍。 – Ninjammer

+0

我明白這將是一個很好的系統。但是,這確實超出了我設計的範圍。我希望StateManager儘可能小,因爲可能只有幾個州(可能是3或4個)。如果僅使用一次而不做太多,我不想過度複雜化代碼。 – RaptorDotCpp