0

以下のようにFSMを実装したい

  • 第 1 レベル最も基本的な状態は BASE_STATE です。すべての状態は BASE_STATE から派生します。
  • 第 2 レベル、WAITING_STATE、RUNNING_STATE、END_STATE など (BASE_STATE から派生。新しい機能はありません)
  • 第 3 レベル, 2 つのグループ状態 (ACTIVE と PASSIVE) があり、次のようなすべての第 2 レベル状態に 1 対 1 で一致します

ACTIVE_WAITING_STATE 、 ACTIVE_RUNNING_STATE 、 ACTIVE_END_STATE など PASSIVE_WAITING_STATE 、 PASSIVE_RUNNING_STATE 、 PASSIVE_END_STATE など

ほとんどの機能は ACTIVE 状態と PASSIVE 状態で共通ですが、いくつかの小さな機能がオーバーライドされているだけです。ここまでは問題ありません。問題は、すべての第 3 レベルのグループが共通の機能を持っていることです。つまり、たとえば、ACTIVE_xxx_STATEs と PASSIVE_xxx_STATEs という 2 つの異なる increment() 関数を実装する必要があります。すべての状態 (例: ACTIVE_WAITING_STATE 、 ACTIVE_RUNNING_STATE 、 ACTIVE_END_STATE 、および PASSIVE 状態) を書き換えずにこれを行う方法

私の質問を明確にするために、私の醜いソルン。問題は、インクリメント関数が同じで、すべての ActivexxxState (および PassiveXXXState) に対して書き直されていることです。

public class BaseState {
    // Lots of functions
}

public class WaitingState extends BaseState{
    // Lots of functions
}

public class RunningState extends BaseState{
    // Lots of functions
}

public class EndState extends BaseState{
    // Lots of functions
}

public Class ActiveWaitingState extends WaitingState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}


public Class ActiveRunningState extends RunningState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}

public Class ActiveEndState extends EndState {
     // Few unique functions
     private void increment() {
         System.out.println("increment active");
     }       
}

public Class PassiveWaitingState extends WaitingState {
     // Few unique functions        
     private void increment() {
         System.out.println("increment passive");
     }       
}

public Class PassiveRunningState extends RunningState {

     private void increment() {
         System.out.println("increment passive");
     }       
}

public Class PassiveEndState extends EndState {

     private void increment() {
         System.out.println("increment passive");
     }       
}
4

3 に答える 3

2

increment() を BaseState の保護されたメソッドにして、一度実装するようにします。


enum を使用してステート マシンを構築する方法に関する記事を書きました。これにより、状態ごとにどこにでもクラスを作成する必要がなくなり、継承もサポートされます。


あなたのコメントに答えて。

abstract class BaseState {
   public abstract boolean isPassive();
   public boolean increment() {
      System.out.println("increment "+(isPassize() ? "passive" : "active");
   }
}

class PassiveState {
   public boolean isPassive() { return true; }
}

複数の isPassive メソッドを持ちたくない場合は、クラスの命名規則を想定できます

public boolean isPassive() { return getClass().getSimpleName().startsWith("Passive"); }
于 2011-06-30T14:28:02.227 に答える
1

あなたの質問を完全に理解しているかどうかはわかりません。とにかく、継承を使用するのではなく、クラスのプロパティのようなアクティブ/パッシブ状態をモデル化することをお勧めします。階層を次のようにします。

public class BaseState {
     boolean active; //active or passive
}

public class WaitingState extends BaseState {

}

...
于 2011-06-30T13:37:48.377 に答える
0

ステート マシンで共通の動作を共有する場合、それを実装するには 2 つの可能性があります。

1)共通の実装を基本状態に追加できるため、基本状態から継承する任意の状態実装から呼び出すことができます。これらのメソッドの可視性は保護されます。

2)私の意見では、より良い解決策は、一般的な動作を、州のクラス階層とはまったく関係のない独自のクラスに移動することです。
したがって、共通の動作を実装し、基本クラスによって参照され、任意の状態から呼び出すことができる戦略クラスについて考えることができます。
ステート マシンとストラテジ クラスの両方のテスト容易性が向上するため、2 番目のソリューションの方が適しています。

于 2011-06-30T14:41:54.313 に答える