Application Development, Product to Market
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use

State Design Pattern Example

10/23/2013

0 Comments

 
State pattern is a behavioral pattern in GoF because it allows to alter its behavior when a context's internal state changes. The pattern handles each state using a separate state object and the transition from one state to another that does not call for if-then statements.
Picture
source: GoF

overview

Think of State pattern as a finite state machine.

State pattern encapsulates all possible concrete States objects into a Context object, and have a variable references the current State object of the context. The association from Context to State hierarchy is a 'basic aggregation' (as opposed to composition aggregation) which means the Part Class (State) instances can outlive its Whole Class (Context).

Whenever a Request() method (e.g. insertCard(), rejectCard(), etc.) is called upon the Context to trigger state transition, the request is delegated to the current State of the context to handle via calling into Handle(context), through which, a State object access Context and transition Context’s current State to the next State after processing the requested action. All methods implemented by State are possible actions to be applied to the state, the target state to transition to is coded in the method as seen in the code example below. 

Alternatively, I've seen implementation of State class be initiated with a Context via constructor, so on delegating request, you'd call into State's Handle() without needing to pass it the Context (instead of calling Handle(context)).

state design pattern code example

Context class:
public class ATMMachineContext {
  // all possible states are in the context
  ATMState hasCard;     
  ATMState noCard;
  ATMState hasCorrectPin;
  ATMState atmOutOfMoney;
  ATMState atmState;
  int cashInMachine = 2000;
  boolean correctPinEntered = false;

  // initialize all possible states
  public ATMMachineContext(){

    hasCard = new HasCard();
    noCard = new NoCard();
    hasCorrectPin = new HasPin();
    atmOutOfMoney = new NoCash();
    atmState = noCard;
    if(cashInMachine < 0){
      atmState = atmOutOfMoney;
    }
  }
  void setATMState(ATMState newATMState){
    atmState = newATMState;
  }
  public void setCashInMachine(int newCashInMachine){
    cashInMachine = newCashInMachine;
  }
  public void insertCard() {
    atmState.insertCard(this);
  }

  public void ejectCard() {
    atmState.ejectCard(this);
  }

  public void requestCash(int cashToWithdraw) {
    atmState.requestCash(this, cashToWithdraw);
  }

  public void insertPin(int pinEntered){
    atmState.insertPin(this, pinEntered);
  }

  public ATMState getCurrentState() { return atmState; }
}
State:
public interface ATMState {
  // Different states expected HasCard, NoCard, HasPin, NoCash
  void insertCard(ATMMachineContext 
machineContext);
  void ejectCard(ATMMachineContext machineContext);
  void insertPin(ATMMachineContext machineContext, int pinEntered);
  void requestCash(ATMMachineContext machineContext, int cashToWithdraw);
}

public class HasCard implements ATMState {
  public void insertCard(ATMMachineContext machineContext) {    
    System.out.println("You can only insert one card at a time");   
  }

  public void ejectCard(ATMMachineContext machineContext) {    
    System.out.println("Your card is ejected");
    machineContext.setATMState(machineContext.getNoCardState());    
  }

  public void requestCash(ATMMachineContext machineContext, int cashToWithdraw) {   
    System.out.println("You have not entered your PIN");        
  }

  public void insertPin(ATMMachineContext machineContext, int pinEntered) {   
    if(pinEntered == 1234){      
      System.out.println("You entered the correct PIN");
      machineContext.correctPinEntered = true;
      machineContext.setATMState(machineContext.getHasPin());      
    } else {     
      System.out.println("You entered the wrong PIN");
      machineContext.correctPinEntered = false;
      System.out.println("Your card is ejected");
      machineContext.setATMState(machineContext.getNoCardState());      
    }  
  }  
}
In Java, you may consider implementing states using enum, see "Java Secret: Using an enum to build a State machine."

when to use state design pattern

  • When the process/behavior is subject to change.

comparison

State vs. Strategy

  • They both have context and both share the same UML but differ quite a bit in intents.
  • State design pattern is used to define and manage state of an object, whereas Strategy pattern is used to define a set of interchangeable algorithm and lets client to choose one of them.
  • States store a reference to the context object that contains them, or got passed the reference to the context. Strategies do not.
  • States provide the underlying implementation for all actions the context object does, whereas Strategies only handle a single, specific task.
0 Comments



Leave a Reply.

    Categories

    All
    Algorithm
    Concurrency
    CQ
    Data Structure
    Design Pattern
    Developer Tool
    Dynamic Programming
    Entrepreneur
    Functional Programming
    IDE
    Java
    JMX
    Marketing
    Marklogic
    Memory
    OSGI
    Performance
    Product
    Product Management
    Security
    Services
    Sling
    Social Media Programming
    Software Development

    Feed Widget

    Archives

    May 2020
    March 2020
    April 2018
    March 2018
    February 2018
    December 2017
    March 2017
    November 2016
    June 2016
    May 2016
    April 2016
    October 2015
    September 2015
    August 2015
    September 2014
    July 2014
    June 2014
    May 2014
    March 2014
    January 2014
    December 2013
    November 2013
    October 2013
    September 2013
    August 2013
    July 2013
    June 2013

    RSS Feed

in loving memory of my mother  and my 4th aunt
Photos used under Creative Commons from net_efekt, schani, visnup, Dan Zen, gadl, bobbigmac, Susana López-Urrutia, jwalsh, Philippe Put, michael pollak, oskay, Creative Tools, Violentz, Kyknoord, mobilyazilar