0

状態パターンなし

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;
        }
    }
}

状態パターン

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");
        }
    }

someMethod()最初のケースではオブジェクトは 1 つしかありませんが、別のケースではメソッドを呼び出すたびに新しいオブジェクトを作成します。

  1. これはパターンの正しい理解ですか?
  2. この問題を解決して、それほど多くのオブジェクトを作成しないようにするにはどうすればよいですか?
  3. このパターンについて他に何を知る必要がありますか?
4

2 に答える 2

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)          
    }
}
于 2012-02-06T20:00:34.127 に答える
2

「古典的な」状態パターンでは、次の状態を決定するのは現在の状態オブジェクトの責任です。これが可能な問題の場合、状態パターンは非常にうまく機能し、クリーンでわかりやすいコードを生成します。

ただし、現在の状態が次の状態を決定できず、この決定を呼び出し元に委譲しなければならない場合、この関数は機能しなくなります。問題が非常に大きい場合、コードはすぐに理解できなくなります。遷移、アクション、およびガードを備えた UML 風のステート マシンを使用することをお勧めします。この場合、状態の変更をテーブル駆動で行うことができます。

于 2012-02-06T21:11:19.580 に答える