状态模式共享状态对象高效和可扩展实现之间的共同知识

State Pattern share common knowledge between state object efficient and extandable implementation

我正在使用状态模式,但我发现的示例是出于教育目的,我想知道在这种模式中 在状态之间共享对象 的最佳实践是什么,即一个布尔值、一个列表以及 用于一个状态对象以更改自动机对象中的状态引用

我将建立一个简单的模型作为示例。

public abstract class State {

    Automata automata;

    public State( Automata automata){
         this.automata = automata;
    }

    public abstract void action();

}

public class State1 extends State {

    public State1(Automata automata){
         super(automata)
    }

    @Override
    public void action() {
        // GET  : Use obj1 
        // POST :Set in automata state to State2 
    }
} 

public class State2 extends State {

     public State2(Automata automata){
         super(automata)
    }

    @Override
    public void action() {
        // GET  :Use obj1 
        // POST :Set in automata state to State1 
    }
}  

public class Automata {

     private State state1 = new State1(this);
     private State state2 = new State2(this);
     private State state = state1;

     public void takeAction() {
         state.action()
     }
}

我尝试了以下解决方案:

  1. 对于 GETobj1 存储在自动机中并使用 getter 和 setter。对于 POST 在自动机中存储状态并使用 getter 和 setter。这种方法将通过使用 getter 使代码不必要地变长,并且随着 obj1 和状态的变化列表变得难以维护。
  2. 使用私有内部 classes。将 State, State1State2 声明为私有内部 classes 并直接访问 obj1 和状态。仅仅因为文件的长度而难以维护和更新。无法与其他人共享 Automata class.
  3. 创建字段public。我不想公开所有这些字段。
  4. 使用 singleton/static class 方法分享 obj1

我不太了解包私有访问。

在我的设计中,我将此模式与模板方法模式结合起来作为辅助信息。

我知道一刀切方法不存在,但是使用此模式的常见最佳实践是什么?

我会这样做:

public class Automata {
  List<String> someList;
  boolean someBoolean;
  private State currentState;

  public void performAction() {
    currentState = currentState.action(this);
  }

  interface State {
    State action(Automata context);
  }

  enum States implements State {
    IDLE {
      @Override
      public State action(Automata context) {
        if (context.someBoolean) {
          return WORKING;
        }
        return this;
      }
    },
    WORKING {
      @Override
      public State action(Automata context) {
        if (context.someList.size() > 7) {
          return IDLE;
        }
        return this;
      }
    }
  }
}

状态的设置现在在 AutomataperformAction() 中完成,无需在每个状态中执行此操作。我使用枚举作为状态的实现,因为当您想将状态实现为纯函数时,它们非常有用。但是,如果您的状态本身不是无状态的,您可能希望将状态实现为静态内部 类.

关注@rinde post,我很好奇这是否是一个可接受的解决方案

public abstract class State {

    public State(){
    }

    public abstract void action(sharedState);

    public class SharedState{
         Obj1 obj1;
         State state1;
         State state2;
         State curState;

         //Getters and setters
    }
}

public class State1 extends State {

    @Override
    public void action(SharedState sharedState) {
        // GET  : Use obj1 
        sharedState.obj1.doSomething()
        // POST :Set in automata state to State2 
        sharedState.curState = sharedState.state2;
    }
} 

//..same for State2

public class Automata {

   State.SharedState sharedState;

   public Automata(){
        sharedState.setState1(new State1());
        sharedState.setState2(new State2());
   }


   public void takeAction() {
       sharedState.getCurrentState().action(sharedState);
   }
}