“The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change it’s class.” - Head First Design Pattern

** Head First Design Patterns (Head First) ** by Elisabeth Freeman, Eric Freeman, Bert Bates, Kathy Sierra

Read more about this title…

Let’s say I’ve got a point of sale terminal used for processing financial transactions. Let’s say that at any given time the terminal can be in 1 of 6 states. Those states are:

Let’s pretend the following is the client code that will use the point of sale terminal to process transactions.

IPosTerminal terminal = new PosTerminal( );
  terminal.SwipeCard( "6278080000008205" );
  terminal.EnterAmount( 99.99 );
  terminal.EnterPin( "8012" );
  terminal.ProcessTransaction( );
  terminal.PrintReceipt( );

When the PosTerminal is first constructed it is immediate put into an Idle State which displays an idle message to screen. The PosTerminal has a property of type IState that all the concrete state types implement.

As actions are performed against the PosTerminal, they are delegated to the current state.

public void SwipeCard( string cardNumber ) {
      _currentState.SwipeCard( cardNumber );
  }

  public void EnterAmount( double amount ) {
      _currentState.EnterAmount( amount );
  }

  public void EnterPin( string pin ) {
      _currentState.EnterPin( pin );
  }

  public void AuthorizeTransaction( ) {
      _currentState.ProcessTransaction( );
  }

  public void PrintReceipt( ) {
      _currentState.PrintReceipt( );
  }

  public void ProcessTransaction( ) {
      _currentState.ProcessTransaction( );
  }

In this implementation I’ve made it the concrete state types responsibility to transition to the next state. For example the IdleState might look like:

 1 public void SwipeCard( string cardNumber ) {
 2       _terminal.Transaction = new PosTransaction( );
 3       _terminal.Transaction.Date = DateTime.Now;
 4       _terminal.Transaction.CardNumber = cardNumber;
 5       _terminal.CurrentState = new CardSwipedState( _terminal );
 6   }
 7 
 8   public void EnterAmount( double amount ) {
 9       Console.Out.WriteLine( "Please swipe a card first." );
10   }

With the state pattern you can re-order states and alter the implementation of a state with out having to change the subject of the state.

DesignPatterns.State.zip (7.13 KB)

comments powered by Disqus