2012-02-06 39 views
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. 这是对模式的正确理解吗?
  2. 我该如何解决这个问题,不创造这么多的对象?
  3. 我还需要了解这种模式吗?
+1

你的第一个例子只有两个状态。在一个更大的例子中,'someMethod()'会变得非常笨拙。不要过于担心创建小型,短暂的物体。垃圾收集器处理得很好。如果对象创建确实成为问题,那么只需在Map或List中保存每个状态类的实例,或者(ab)为此目的使用'enum'。 – Barend 2012-02-06 19:55:20

+0

感谢您的回复。 – drifter 2012-02-06 19:59:31

回答

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 2012-02-06 20:05:26

+0

你是对的。只有2个状态可以工作 – Cratylus 2012-02-06 20:41:23

2

在“经典”的状态的图案,它是当前的状态对象的责任,以确定下一个状态。对于可能出现的问题,状态模式运行良好,并生成清晰易懂的代码。

但是,当当前状态不能确定下一个状态时,它会中断,但必须将此决定委托给调用者。如果问题足够大,代码很快就会变得不可理解,最好使用带有转换,动作和警卫的UMLish状态机,状态变化可以由表驱动。

+0

我认为你所描述的问题可以通过保持上下文信息/状态来解决states.Ie每个状态都有一个上下文数据对象,它提供足够的信息来确定下一个状态。调用者负责提供当然上下文 – Cratylus 2012-02-06 22:06:10

+0

上下文的使用并不会真正改变任何事情。你如何在两个不同的地区重复使用状态对象? – 2012-02-06 22:14:25

+0

不知道我现在跟着你 – Cratylus 2012-02-06 22:18:32