2016-09-29 3 views
2

私はreading up on State Machinesだったので、私は次のプロジェクトに使う必要があります。私がオンラインで見つけたほとんどの例は、StateAからStateBへ行く方法を示しています。しかし、次の希望状態が隣接状態でない場合はどうなりますか?これを達成するための共通のパターン/プラクティスはありますか? Javaでは理想的ですが、他のプログラミング言語も同様に読むことができます。ターゲットステートが次のステートでない場合に使用するステートマシンの設計にはどのようなものがありますか?

# Scenario 1: Desired State == Work 
Forgot car keys, so you have to return to previous state and then move forward in states again. 

# Scenario 2: Desired State == Work 
Have car keys, so move forward in states to get to Desired State. 

を解決する

# Example States 
WakeUp->Get Dressed->Get Car Keys->Get in Car->Drive to Work->Work 

Current State: Get in Car 

問題それは、ステートマシンはエレガントにこの問題を解決しないかもしれないと私はちょうどロジックをクラフトに手する必要があり、私は気にしない可能性が非常に高いのですが、私は」と思いました他の人が理解できるように、共通のデザインパターンに従ってください。

上記の例から、私は「内部」状態について心配する必要はありません。これは私が取り組んでいるプロジェクトでも当てはまります。そのような場合には、可能な解決策に違いがあります。

答えて

4

ここでは、ステートマシンを定義する簡単な方法があります。

必要なすべての状態を列挙型で定義します。

enum StateType { 
    WAKE_UP, GET_DRESSED, GET_CAR_KEYS, GET_IN_CAR, DRIVE_TO_WORK, WORK 
} 

状態を制御するステートマシンと、ステートマシン上でアクションを実行するステートインターフェイスを持っています。状態は次の状態に戻ります。

interface State { 
    StateType next(StateMachine sm); 
} 

class StateMachine { 
    private Map<StateType, State> states = new HashMap<StateType, State>() {{ 
     put(StateType.WAKE_UP, new WakeUpState()); 
     put(StateType.GET_DRESSED, new GetDressedState()); 
     put(StateType.GET_CAR_KEYS, new GetCarKeysState()); 
     put(StateType.GET_IN_CAR, new GetInCarState()); 
     put(StateType.DRIVE_TO_WORK, new DriveToWorkState()); 
     put(StateType.WORK, new WorkState()); 
    }}; 

    private StateType currentState = StateType.WAKE_UP; 

    private boolean hasCarKeys; 

    public boolean hasKeys() { 
     return hasCarKeys; 
    } 

    public void setHasKeys(boolean hasKeys) { 
     hasCarKeys = hasKeys; 
    } 

    public void update() { 
     currentState = states.get(currentState).next(this); 
    } 
} 
+0

ニース1ステートマシンを定義する複数の種類の

class GetInCarState implements State { @Override public StateType next(StateMachine sm) { if (sm.hasKeys()) { return StateType.DRIVE_TO_WORK; } return StateType.GET_CAR_KEYS; } } 

をこの状態を実装します。いくつかの提案:(1)StateType.DriveToWork - おそらくDRIVE_TO_WORKを意味しました。 (2) 'class GetInCarState'と' StateType.DRIVE_TO_WORK'をenum型の中で 'next'メソッドを動かすことで組み合わせることで、あなたの例を邪魔することができます - StateTypeによるMapの必要性もなくなります。 – bashnesnos

+0

catch on(1):)ありがとうございました。私はまた、enumが 'next'メソッドを定義することを考えていましたが、それに対して決めました。実装を列挙型に連結しないことにより、各状態に対して複数の表現を持つことが可能です。これは、テストのためのモック状態を作成し、まったく新しい列挙型を作成することなく後で同様のステートマシンを作成するのに役立ちます。 – flakes

+1

ええ、これはすべてのOOP時間の大きな問題です。事柄を抽象的にするかどうかを決めることはできません:-)最初に抽象化する方が好きですね:-) – bashnesnos

関連する問題