2

I would like to create a state machine.

Each State would have its run method, and, according to some logic would then set a next state.


  • Option 1:

If each state is responsible for determining a next state, then it would have a next_state() which would return a pointer or an id of some other state, thus forcing each state to know about the existence of other states ==> bad.

  • Option 2:

If some other entity is responsible for the next state, then some logic there would have to calculate the next state, but would depend on current state, thus breaking the current state's encapsulation (or force the creation of a getter-like method, that would in reality be option 1) ==> bad


So, I can't come up with a way that doesn't break encapsulation for the part of a state machine that decide the next step.

I would like to hear the best practice in this case, as even Wikipedia doesn't shed light on this.

3
  • Depends, are we talking Object Oriented Programming, Procedural Programming, Functional?. Are we parsing? Modal rendering? etc. There isn't one best practice because there is no one application for finite state machines. There's a whole lot of "it depends..." going on here. Feb 25, 2020 at 16:36
  • NOTE: in the Gang of Four book on object oriented patterns, your Option 1 is exactly what they propose. There is no clean answer here, so try not to overthink it. NOTE: a state object only needs to know about the following state(s), not all of the state objects. Feb 25, 2020 at 16:40
  • 1
    Encapsulation is not impacted here. Isolation is. Encapsulation means the internal structure and state of the object is not exposed outside of the object. Isolation means that an object does not need to know about the existence of other objects. It should be a goal to eliminate unneeded dependencies, but you cannot write software if an object does not ever interact with other objects--even of the same kind. Feb 25, 2020 at 16:44

1 Answer 1

5

Sometimes it takes multiple objects for a whole abstraction.

The GoF state pattern is very general purpose.  Each state needs to know only about successor states, so it can transition to them.  Since each state is a class, states can be subclassed (for hierarchical state machine); states can have instance variables separate from each other, and, since states are dynamically created, their instance variables have proper lifetime — just for the duration of being in that state.


If you don't have those requirements, however, a single class state machine may suffice — a simple state machine can capture context (current state) and transitions within one class, describing the states with just an enum.


The important thing is how the state machine looks from the outside, for the consuming client — so that the internal implementation could use the GoF multi-class approach, or something simpler, or more complex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.