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

Rad*_*scu 5 java design-patterns state-pattern

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

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

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()
     }
}
Run Code Online (Sandbox Code Playgroud)

我尝试过以下解决方案:

  1. 对于自动机中的GET存储obj1并使用 getter 和 setter。对于自动机中的POST存储状态并使用 getter 和 setter。这种方法将通过使用 getter 使代码变得不必要的长,并且随着 's 和 states 的列表的变化而变得难以维护obj1。
  2. 使用私有内部类。将State, State1and声明State2为私有内部类并直接访问obj1and 状态。由于文件长度而难以维护和更新。不能与其他Automata班级共享。
  3. 公开字段。我不想暴露所有这些字段。
  4. 使用单例/静态类方法进行obj1共享

我不太发现包私有访问。

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

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

rin*_*nde 4

我会做这样的事情:

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;
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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