2012-02-06 6 views
0

最初のケースで状態パターンは無理解状態のパターン

public static void main(String[] args) { 
     Context context = new Context(); 
     context.setState(new State1()); 
     for (int i = 0; i < 10; i++) 
      context.someMethod(); 
    } 

    static class Context { 
     State state; 

     void setState(State state) { 
      this.state = state; 
     } 

     void someMethod() { 
      state.someMethod(); 
      if (state instanceof State1) { 
       state = new State2(); 
      } else { 
       state = new State1(); 
      } 
     } 
    } 

    static interface State { 
     void someMethod(); 
    } 

    static class State1 implements State { 
     @Override 
     public void someMethod() { 
      System.out.println("StateA.SomeMethod"); 
     } 
    } 

    static class State2 implements State { 
     @Override 
     public void someMethod() { 
      System.out.println("StateB.SomeMethod"); 
     } 
    } 

public static void main(String[] args) { 
    Context c = new Context(); 
    for (int i = 0; i < 10; i++) 
     c.someMethod(); 
} 

static class Context { 
    public static final int STATE_A = 0; 
    public static final int STATE_B = 1; 

    private int state = STATE_A; 

    public void someMethod() { 
     switch (state) { 
     case STATE_A: 
      System.out.println("StateA.SomeMethod"); 
      state = STATE_B; 
      break; 
     case STATE_B: 
      System.out.println("StateB.SomeMethod"); 
      state = STATE_A; 
      break; 
     default: 
      break; 
     } 
    } 
} 

状態パターンがなければ、私たちは、1つのオブジェクトのみを持っているが、我々はsomeMethod()メソッドを呼び出すときに別で、私たちは毎回新しいオブジェクトを作成します。

  1. これはパターンを正しく理解していますか?
  2. 非常に多くのオブジェクトを作成しないようにこの問題を解決するにはどうすればよいですか?
  3. このパターンについてさらに知りたいことがありますか?
+1

最初の例には2つの状態しかありません。より大きな例では、 'someMethod()'は非常に扱いにくくなります。小さな、短命のオブジェクトを作成することについてあまり心配しないでください。ガベージコレクタはこれらをうまく処理します。オブジェクトの作成が問題になる場合は、すべての状態クラスのインスタンスをマップまたはリストに保持するか、目的のために(en) 'enum'を使用します。 – Barend

+0

ご返信ありがとうございます。 – drifter

答えて

2

さてあなたはより良い行うことができます。

あなたは新しい状態に進めるためのinstanceofをチェックしてはいけません。
各状態は、実行するとすぐに次の状態に移ることができます(サンプル:コンパイルしようとしていない)。

例:「古典的な」状態パターンで

class Context { 
    State state;     

    public Context(){ 
     state = STATE1;//Starting state 
    } 

    void someMethod() { 
      state.someMethod(this); //Which is it?State1 or state 2??? 
    } 

} 

public interface States { 
    public static final State STATE1 = new State1(); 
    public static final State STATE2 = new State2(); 
    //more states here 

} 

class State1 implements State { 
    @Override   
     public void someMethod(Context ctx) {    
     System.out.println("StateA.SomeMethod"); 
     ctx.setState(STATE2); //advance to next state   
    } 
} 

class State2 implements State { 
    @Override   
    public void someMethod(Context ctx) {    
    System.out.println("StateB.SomeMethod"); 
    ctx.setState(STATE1); //advance to next state (back to state 1)   
    } 
} 
+0

また、State1をContext内の内部クラスにすることもできます。そうすれば、someMethod()内のContextへの参照を渡す必要はありません。 – JohnnyK

+0

あなたは正しいです。ちょうど2つの州でも同様に動作します。 – Cratylus

2

、次の状態を決定するために、現在の状態オブジェクトの責任です。これが可能な問題については、状態パターンは非常によく機能し、きれいで分かりやすいコードを生成します。

ただし、現在の状態が次の状態を判断できない場合は分解しますが、この決定を呼び出し元に委任する必要があります。問題が十分に大きければ、コードは間もなく理解できなくなり、ステートの変更をテーブル駆動できるトランジション、アクション、ガードを備えたUMLishステートマシンを採用する方がよいでしょう。

+0

私はあなたが記述した問題は、コンテキスト情報/状態を私は各ステートには、次のステートを決定するのに十分な情報を提供するコンテキストデータオブジェクトが関連付けられています。コンテキストを提供するのは呼び出し元の責任です。 – Cratylus

+0

コンテキストの使用は実際に何も変更しません。どのように2つの異なる地域で状態オブジェクトを再利用しますか? –

+0

私は今あなたに従っているのか分かりません – Cratylus

関連する問題