Question

I've come across some examples of state machines written as enumerations. For instance:

public enum State {
    INITIAL {
        @Override
        public State process(char ch) { return MIDDLE; }
    },

    MIDDLE {
        @Override
        public State process(char ch) {
            switch (ch) {
                case 'a': return INITIAL;
                default: return FINAL;
            }
        }
    },

    FINAL {
        @Override
        public State process(char ch) { return FINAL; }
    };

    public abstract State process(char ch);

    public static State initial() { return INITIAL; }
}

What concerns me, is having the constants know each other. Their implementations are subject to change, and if constants are added (or removed) more changes are implied.

However, all changes are contained in the enumeration, unless outside code references the constants directly and makes assumptions about the transition table.

So, is this code highly coupled, loosely coupled, or is it subjective?

Was it helpful?

Solution

I'd say this is too tightly coupled for a flexible tool.

Something looser would be much more flexible:

public enum State {
  INITIAL,
  MIDDLE,
  FINAL;
  public static State initial() {
    return INITIAL;
  }

}

// A 'null' for the Character matches anything.
static Map<Pair<State,Character>, State> machine = new HashMap<>();
static {
  // Always transit from INITIAL to MIDDLE
  machine.put(new Pair<State,Character>(State.INITIAL,null), State.MIDDLE);
  // An 'a' transitrs us to FINAL
  machine.put(new Pair<State,Character>(State.MIDDLE,'a'), State.FINAL);
  // Anything else takes us back to INITIAL
  machine.put(new Pair<State,Character>(State.MIDDLE,null), State.FINAL);
  // Stay in FINAL once there.
  machine.put(new Pair<State,Character>(State.FINAL,null), State.FINAL);

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top