The demo code is located here. To compile and run the code:
javac StateMachineDemo.java
java StateMachineDemo
The output should look like this:
Transition from 'Idle' -> 'Building Widget' results in action 'Build Widget'
Error! Transition from 'Packing Widget' -> 'Idle' is invalid!
In state 'Packing Widget', action 'Ship Widget' results in new state 'Shipping Widget'
Error! Action 'Build Widget' while in state 'Canceled' is invalid!
This example includes a state map that simulates a factory building widgets. A few points of explanation are in order.
- The FiniteStateMachine class is static, and I did that purposefully, because I wanted to ensure that I was not needlessly creating and destroying instances of the FSM in my application.
- The state map looks like this:
private static Map<List<state>, action> stateMap = new HashMap<>();
It is a hashmap of lists of states to an action. By using a list of states (as opposed to a hashmap of states), we can have the same starting state mapping to several different ending states depending on the action. This ability is required for non-deterministic FSMs.
- Depending on your application, you may know the starting and ending state, but not the resulting action. Or, you may know the starting state and the action, but not the ending state. The example code contains two Transition methods, one for each case.
- If Transition() is called with an invalid combination of states or state and action, it will throw a StateTransitionException.
This example class could be grown or extended into a more fully featured library, but I kind of enjoy the KISS approach. Anyway, hope you find it useful, enjoy.