Can a state machine transition depend on the previous state

design-patternsfinite-state machine

I was wondering what the state machine for a video player would be like.

I can think of two states : playing and paused.

  • When the video is playing and the user clicks on a point in the progress bar the video is paused (the video player transitions from the playing state to paused state) until the user stops pressing the mouse button.
    When the mouse is released the video begins to play again from the selected point (the video player transitions from the paused state to the playing state).
  • However if the video was paused before the user clicked on the progress bar the video jumps to the specified point but does not start playing (the video player remains in the paused state).

The state transitions would be :

playing (begin click on progress bar)–> paused (end click on progress bar)–> playing paused (begin click on progress bar)–> paused (end click on progress bar)–> paused

If there was a method to change the position of the video in the paused state, then calling that method would result in a different state depending on the previous state. I was wondering if there is an alternate state machine design for a video player where the transitions from each state do not depend on any previous state.

Best Answer

If you want to hold onto "classical" state machines whose transition functions only depend on the current state and incoming inputs you have to rethink how you want to model the application's state.

Formally, you can simulate transitions depending on the previous state (in terms of your current application) by building a new state machine which has pair states with each pair containing combinations of two of the original state machine's states. Conceptually one of the pair's components stands for your current main state while the other one describes the previous state.

For each original transition t from state x to state y you'll get transitions t' from any state of the form (*, x) to state (x, y) (here the first component encodes the previous main state).

Then modify the resulting state machine to your needs such that you're actually using the previous main state (first component).

You may reduce this "product state machine" by eliminating states/combinations which are impossible to reach or by collapsing state-sets (*,s) which are equivalent regarding the ingoing and outgoing transitions to single states.

Perhaps in your case you can directly introduce SOME pair states instead of going through the whole formal ceremony. Just be careful to consider all important combinations.

In your example the resulting state machine is not much different from the original one. Some of the states and transitions you might get from such a construction are (now with (x,y) written as x_y):

playing  --(mousedown)-->  playing_paused  --(mouseup)-->  playing
paused   --(mousedown)-->  paused_paused   --(mouseup)-->  paused

Notice how the target state on mouseup events at the middle paused state differs, depending on the encoded previous state.

Related Topic