The State Pattern

Posted on August 26, 2007 @ 21:35 books csharp designpatterns

“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:

  • **Idle State: During this state an idle message is displayed on the screen of the POS terminal.
  • **Card Swiped State: The terminal enters this state when a card is swiped.
  • **Amount Entered State: The terminal enters this state when the transaction amount is entered.
  • **PIN Entered State: The terminal enters this state when the customer enters their PIN.
  • **Processing Transaction State: The terminal enters this state when it connects to a financial processor to process the transaction.
  • **Transaction Approved State: The terminal enters this state when the transaction has been process and has been approved.
  • **Transaction Rejected State: The terminal enters this state when the transaction was processed but was rejected.

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
2
3
4
5
6
7
8
9
10
  public void SwipeCard( string cardNumber ) {
      _terminal.Transaction = new PosTransaction( );
      _terminal.Transaction.Date = DateTime.Now;
      _terminal.Transaction.CardNumber = cardNumber;
      _terminal.CurrentState = new CardSwipedState( _terminal );
  }

  public void EnterAmount( double amount ) {
      Console.Out.WriteLine( "Please swipe a card first." );
  }

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)