In this article I will introduce the readers to the state machine model and also create a simple working state machine sample using the .NET framework in C# language.
What is a State Machine?
Any device that changes its state from one to another due to some actions are defined to be state machines. For example an ATM machine, traffic signal, remote control, the computer itself, etc. Most software applications also depend and operate based on the state. There are two types of state machines.
1. Finite state machine – A state machine holding a defined set of states and they work within that.
2. Infinite state machine – Here the states can be many and cannot be predefined.
Most common state machines are finite ones.
Composition of a State Machine
The following things collectively make an effective finite state machine.
State:
A defined set of states. At any point of time the state machine will be in any one of the defined states. For example Red, Green and Yellow in a traffic signal system.
State Transition:
A state machine changing its state from one to another is called State Transition. Usually there will be a state transition table built that will contain the state sequences and also metadata saying which event will cause which state transition.
Triggers:
Triggers are the points that induce the state transition in a state machine.
Events or Actions:
Actions are performed by the state machines when a particular state is attained and exited. There will be Entry and Exit actions for each state.
Guard Condition:
This is the piece of component that validates the transition and ensures that no invalid state changes are carried out.
State Machine Vs State Pattern
State pattern is one among the Gang of Four patterns. Most people have an impression that state machine and state pattern are different but the truth is state pattern is one way to implement a state machine. There are other ways available to build sophisticated state machines including all the components mentioned in the above section.
Traffic Signal State Machine Example
Let us create a simple state machine using a state pattern in .NET framework. The state machine that we are going to build is a Traffic Signaling system, which changes the signals within specific time intervals once the system is started.
Create a state interface named IState, which will be implemented by all the available states.
namespace FiniteStateMachine { public interface ISignalState { void Enter(TrafficSystem system); } }
Next let us create the states for the traffic signal. The states will be Red, Green and Yellow.
namespace FiniteStateMachine { public class RedState : ISignalState { const int SIGNAL_TIME = 5000; public void Enter(TrafficSystem system) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Entered Red."); Thread.Sleep(SIGNAL_TIME); system.NextTrafficSignal = new GreenState(); system.ChangeSignal(); } } } namespace FiniteStateMachine { public class GreenState : ISignalState { const int SIGNAL_TIME = 10000; public void Enter(TrafficSystem system) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Entered Green."); Thread.Sleep(SIGNAL_TIME); system.NextTrafficSignal = new YellowState(); system.ChangeSignal(); } } } namespace FiniteStateMachine { public class YellowState : ISignalState { const int SIGNAL_TIME = 3000; public void Enter(TrafficSystem system) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Entered Yellow."); Thread.Sleep(SIGNAL_TIME); system.NextTrafficSignal = new RedState(); system.ChangeSignal(); } } }
Now comes the traffic system that holds an initial state, which is Green and then changes its context state periodically. It exposes a Start function, which is a handle for the clients to kick start the traffic system.
namespace FiniteStateMachine { public class TrafficSystem { public ISignalState NextTrafficSignal { get; set; } public void Start() { NextTrafficSignal = new GreenState(); NextTrafficSignal.Enter(this); } public void ChangeSignal() { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("###########Signal changed##########"); NextTrafficSignal.Enter(this); } } }
Now we are good to hook it up to the client, which is a console app Main function in our case.
class Program { static void Main(string[] args) { TrafficSystem system = new TrafficSystem(); system.Start(); Console.ReadLine(); } }
Run the application and you should see the signal changing behavior as shown in Fig 1.0.
Fig 1.0: Signal Changing Behavior
It is not only about creating the state machine application but also can be extended into creating state machine frameworks that can be used by other applications. .NET framework has integrated the state machine framework in the form of Workflow foundation.
Happy reading!