Pregunta

Without State pattern

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

State Pattern

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

In first case we have only one object but in another we create new object every time when we call someMethod() method.

  1. Is this a correct understanding of the pattern?
  2. How can I solve this problem to not create so many objects?
  3. What else do I need to know about this pattern ?
¿Fue útil?

Solución

Well you can do better:

You must not check the instanceof to advance to new state.
Each state should be able to go to the next as soon as it runs (Sample:Not even tried to compile).

Example:

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

Otros consejos

In the "classical" state pattern, it is the current state object's responsibility to determine the next state. For the problems where this is possible, the state pattern works very well and produces clean and comprehensible code.

However, it breaks down when the current state cannot determine the next state, but must delegate this decision to the caller. If the problem is sufficiently large, the code will soon be incomprehensible and it is better to employ a UMLish state machine with transitions, actions and guards where the state changes can be table driven.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top