SDSU CS 635 Advanced Object-Oriented Design & Programming
Spring Semester, 2001
State
Previous    Lecture Notes Index    Next    
© 2001, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 29-Mar-01

Contents of Doc 13, State


References

Design Patterns: Elements of Resuable Object-Oriented Software, Gamma, Helm, Johnson, Vlissides, Addison Wesley, 1995, pp. 305-314

The Design Patterns Smalltalk Companion, Alpert, Brown, Woolf, Addision-Wesley, 1998, pp. 327-338



Doc 13, State Slide # 2

State

Example - SPOP

Simple Post Office Protocol

SPOP is used to download e-mail from a server

SPOP supports the following command:


USER & PASS Commands


USER with a username must come first
PASS with a password or QUIT must come after USER

If the username and password are valid, then the user can use other commands

LIST Command

Arguments: a message-number (optional)

If it contains an optional message number then returns the size of that message

Otherwise return size of all mail messages in the mailbox

Doc 13, State Slide # 3
RETR Command

Arguments: a message-number

Returns: the mail message indicated by the number


QUIT Command

Arguments: none

Updates mail box to reflect transactions taken during the transaction state, then logs user out

If session ends by any method except the QUIT command, the updates are not done



Doc 13, State Slide # 4
The Switch Statement

class SPop
   {
   static final int HAVE_USER_NAME = 2;
   static final int START = 3;
   static final int AUTHORIZED = 4;
   private int state = START;
   
   String userName;
   String password;
   
   public void user( String userName ) {
      switch (state) {
         case START:  {
            this.userName = userName;
            state = HAVE_USER_NAME;
            break;
         } 
         case HAVE_USER_NAME:  
         case AUTHORIZED:{
            endLastSessionWithoutUpdate();
            goToStartState()
            }
         }
      }

Doc 13, State Slide # 5
Implementation with Switch Statement Cont.

   public void pass( String password )
      {
      switch (state)
         {
         case START:  {
            giveWarningOfIllegalCommand();
            }
         case HAVE_USER_NAME: {
            this.password = password;
            if ( validateUser() )
               state = AUTHORIZED;
            else {
               sendErrorMessageOrWhatEver();
               userName = null;
               password = null;
               state = START;
            }
         case AUTHORIZED: {
            endLastSessionWithoutUpdate();
            goToStartState()
         }
         }
      }
   etc.   
   }


Doc 13, State Slide # 6
Using Polymorphism Implementation


class SPop {
   private SPopState state = new Start();
      
   public void user( String userName ) {
      state = state.user( userName );
   }
   
   public void pass( String password ) {
      state = state.pass( password );
   }
   
   public void list( int messageNumber ) {
      state = state.list( massageNumber );
   }
   
   etc.


Doc 13, State Slide # 7
SPopStates
Defines default behavior

abstract class SPopState {
   public SPopState user( String userName ) {
      return goToStartState(); 
   }
   
   public SPopState pass( String password ) {
      return goToStartState(); 
   }
   
   public SPopState list( int massageNumber ) {
      return goToStartState(); 
   }
   
   public SPopState retr( int massageNumber ) {
      return goToStartState(); 
   }
   
   public SPopState quit(  ) {
      return goToStartState(); 
   }
   protected SPopState goToStartState()  {
      endLastSessionWithoutUpdate();
      return new StartState();
   }
}


Doc 13, State Slide # 8
SpopStates - Continued

class Start extends SPopState {
   public SPopState user( String userName ) {
      return new HaveUserName( userName );
   }
}
   
class HaveUserName extends SPopState {
   String userName;
   
   public HaveUserName( String userName ) {
      this.userName = userName;
   }
      
   public SPopState pass( String password ) {
      if ( validateUser( userName, password )
         return new Authorized( userName );
      else
         return goToStartState();
   }
}


Doc 13, State Slide # 9
State

Intent

Allow an object to alter its behavior when its internal state changes. The object will appear to change it class.



Applicability


Use the State pattern in either of the following cases:




Doc 13, State Slide # 10

Issues

How much State in the State


In Example:


All the state & all real behavior is in SPopState & subclasses

This is an extreme example

In general the Context will have data & methods


That is only some aspects of the Context will alter its behavior


Doc 13, State Slide # 11
Issue

Who defines the state transitions?

The Context



class SPop
   {
   private SPopState state = new Start();
      
   public void user( String userName )
      {
      state.user( userName );
      state = new HaveUserName( userName );
      }
   public void pass( String password )
      {
      if ( state.pass( password ) )
         state = new Authorized( );
      else
         state = new Start();
      }


Doc 13, State Slide # 12
Who defines the state transitions?

The State


class SPop
   {
   private SPopState state = new Start();
      
   public void user( String userName )
      {
      state = state.user( userName );
      }
   
   public void pass( String password )
      {
      state = state.pass( password );
      }
   
   public void list( int messageNumber )
      {
      state = state.list( massageNumber );
      }


Doc 13, State Slide # 13
Issue

Sharing State Objects


Multiple contexts (SPops) can use the same state object if the state object has no instance variables

A state object can have no instance variables if:




Doc 13, State Slide # 14
Storing Instance Variables Elsewhere

Variant 1

SPop stores them and passes them to states

class SPop
   {
   private SPopState state = new Start();
   
   String userName;
   String password;
      
   public void user( String newName )
      {
      this.userName = newName;
      state.user( newName );
      }
   
   public void pass( String password )
      {
      state.pass( userName , password );
      }


Doc 13, State Slide # 15
Storing Instance Variables Elsewhere

Variant 2

SPop stores them and states get data from SPop

class SPop {
   private SPopState state = new Start();
   
   String userName;
   String password;
      
   public String userName() { return userName; }
   
   public String password() { return password; }
   
   public void user( String newName ) {
      this.userName = newName ;
      state.user( this );
   }
   etc.

class HaveUserName extends SPopState {
   public SPopState pass( SPop mailServer ) {
      String useName = mailServer.userName();
      etc.
   }
}

Doc 13, State Slide # 16
Issue

Creating and Destroying State Objects


Options:




Doc 13, State Slide # 17
Issue

Changing the Context Class for Real


Some languages allow an object to change its class


   | context |
   context := Start new.
   context changeClassTo: HaveUserName.
   context changeClassTo: Authorized.
So why not forget State pattern and use:



In VisualWorks Smalltalk

In CLOS the State pattern may not be needed

Doc 13, State Slide # 18

Consequences






Doc 13, State Slide # 19

State Verses Strategy


How to tell the difference

Rate of Change
Strategy
Context object usually contains one of several possible ConcreteStrategy objects

State
Context object changes its ConcreteState object over its lifetime

Exposure of Change

Strategy
All ConcreteStrategies do the same thing, but differently
Clients do not see any difference in behavior in the Context

State
ConcreteState act differently
Clients see different behavior in the Context


Copyright ©, All rights reserved.
2001 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.

Previous    visitors since 29-Mar-01    Next