1

私はゲームの StateManager を書いています (私は C++ と SFML を使用していますが、これは OOP 言語に関する質問であるため、言語固有の要素を非表示にしようとしました)。StateManager が現在のアクティブな状態を更新するセットアップがあります。ただし、State はアクティブな状態を変更できる必要があるため (たとえば、メニューで [再生] を押すと PlayingState が開始されます)、State クラスで StateManager への参照を保持します。

わかりやすくするために、UML ダイアグラムを次に示します。 UML ダイアグラム

ご覧のとおり、StateManager と State はどちらも相互に参照しています。スパゲッティコードを回避するにはどうすればよいですか? StateManager をシングルトン クラスにする必要がありますか? ところで、ゲーム クラスはシングルトン クラスにする必要がありますか? これは簡単にできますが、自分のゲーム内の他のクラスがゲーム クラスや statemanager クラスにアクセスできるのはあまり好きではありません。たとえ私が唯一のプログラマーであってもです。

4

2 に答える 2

1

双方向参照に問題はありません。QWidgets の Qt の親子モデルを見てください。各状態が 1 つの StateManager にのみ影響を与えることができる場合は、各状態がその構築で StateManager の「親」へのポインターを取得するようにするか、後で設定します。StateManager はコレクション内の「子」を追跡でき、各子は親が誰であるかを知っているため、親に変更を通知できます。

編集: 最初に確認することは、State クラスを分割することだと思います。現在、状態とその状態に変化するアクションの両方を表しています。アクションは、状態を変更するように指示するために、StateMachine の知識を持っている必要があります。状態は StateMachine の内部にある必要があります。

于 2013-04-02T09:34:25.243 に答える
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」がどこから来るか (制御の反転) は気にせず、単にそれを使用していることにも注意してください。

IStateMachine必要に応じて、別の関数をfor に追加できGetStates()ます。

最終的には、これらのコントラクトを使用して結合を回避します。つまり、 and の実装を完全に置き換えることができIStateManager(それが契約に準拠していると仮定して)、MenuState引き続き正常に動作します。

于 2013-04-02T09:39:36.570 に答える