5,316,172 members and growing! (18,585 online)
Email Password   helpLost your password?
Development Lifecycle » Design and Architecture » General     Beginner License: The Code Project Open License (CPOL)

Understanding State Pattern in C++

By Sarath.

A very simple way to understand State Design Pattern
VC6, C++, Windows, Visual Studio, Dev

Posted: 2 Jun 2006
Updated: 25 Jun 2006
Views: 28,112
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
27 votes for this Article.
Popularity: 4.60 Rating: 3.21 out of 5
4 votes, 14.8%
1
4 votes, 14.8%
2
6 votes, 22.2%
3
6 votes, 22.2%
4
7 votes, 25.9%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Sample Image - StatePattern.gif

Introduction

State pattern is a behavioral type design pattern which is widely used in different applications especially in 3D-Graphics applications and applications for devices. In object oriented design, object can change its behavior based on its current state. A state pattern design implements state and behavior of an object. By using state pattern, we can reduce the complexity in handling different states of an object. This will help us to easily maintain code in future.

Legacy method of handling state of an object

There are alot of applications which need to maintain different states on different contexts. Mainly, it comes in the matter of 3D-Applications and devices. Without using state pattern, normally we are handling the state as follows
class MyDevice
{
    int m_nCurrentState;

public:
    MyDevice()
    {
        m_nCurrentState= STATE_OFF;
    }
    // Function handling the state changes
    void HandleState();
};

void MyDevice::HandleState()
{
    /* changing state depends on the current state */
   if(STATE_OFF == m_nCurrentState)
   {
       m_nCurrentState = STATE_ON;
   }
   else if(STATE_ON == m_nCurrentState)
   {
       m_nCurrentState = STATE_ACQUIRING;
   }
   else if(STATE_ACQUIRING == m_nCurrentState)
   {
       m_nCurrentState = STATE_SAVE;
   }
  ....
  ....
  // We can add more states here
}
What the problem with the above code is, usually the state changing and other activities will be centralized, so that the main function doing this activities will get complex and lengthy if there are many states are to be handled. This function will also get complex in the matter of maintainability. For handling few number of states, this aproach is most suitable and easy to handle. The state pattern comes when complexity matters.

The concept behind the state pattern

In state pattern, an object can have different states each state knows what its next state is. By using this architecture we can add or remove a state at ease. This architecture mainly consists of 3 types of classes.

1. Context Class
This class is the one which has the states. The application will be using (interfering with) this class. The class is responsible to maintain current state.

2. State Class
This is an abstract base class which can hold the different states (sub classes). The context class will be using this class pointer as its member to point the current state.

3. Concentrate Class
This class implements the behavior of the state and behavior of the object.

Example: State Change

Here I’m taking the Sun as example: A person who is living in earth can view sun in different states (even it remains constant). Those are morning, noon, afternoon, evening, night. For Simplicity I’m taking 3 states Morning, Evening and Night.
The Sun is starting (Initial state) with state Morning.
Morning knows that sun will move to Evening after its time period, Evening knows that beautiful Night will come after its turn and finally after a dark Night, it knows that Sun will change to a cool Morning. In this architecture each state has a next state. When the object receives a command to change its state, it will ask the current state, what its next state is and modify itself to the new state returned.

Adding a New State

Suppose we want to add a new state Noon for Sun. We can do in simple steps as described below. Take Noon as example
1. Define a new concentrate class (Noon class)
2. Define its next state (Evening)
3. Give this state as the next state of another state (change Morning’s next state from Evening to Noon).

Code

State class

class CBaseState
{
public:
    // Pure virtual function
    virtual CBaseState* GetNextState() = 0;
    // print the string
    virtual    char* ToString() = 0;
};

Concetrate classes

//////////////////////////////////////////////////////////////////////////
// State Morning
//////////////////////////////////////////////////////////////////////////
class CMorning : public CBaseState
{
public:
    virtual CBaseState* GetNextState();
    virtual    char* ToString();
};

//////////////////////////////////////////////////////////////////////////
// State Evening
//////////////////////////////////////////////////////////////////////////
class CEvening : public CBaseState
{
public:
    virtual CBaseState* GetNextState();
    virtual    char* ToString();
};

//////////////////////////////////////////////////////////////////////////
// State night
//////////////////////////////////////////////////////////////////////////
class CNight: public CBaseState
{
public:
    virtual CBaseState* GetNextState();
    virtual    char* ToString();
};

Context Class

//////////////////////////////////////////////////////////////////////////
// Context Class
//////////////////////////////////////////////////////////////////////////

class CSun
{
public:
    CSun();
    CSun(CBaseState* pContext /* Pass Allocated memory */);
    ~CSun();
    // Handles the next state
    void StateChanged();
    char* GetStateName();
protected:
    void DoCleanUp();
    // Pointer which holds the current state
    // Since this is and base class pointer
    // of Concentrate classes, it can holds their objects
    CBaseState* m_pState;
};

When State Change Request Comes

In the above example, the sun will be initialized to any of the states for e.g say morning.
CSun objSun(new CMorning);

If we need to change its current state to next state, it is possible to by calling StateChanged interface proveided by the context class.
See sample code snippet for initializing and changing the state
CSun objSun(new CMorning);
printf("\n\nSun Says Good %s !!!",objSun.GetStateName());
// inform that state has been changed
objSun.StateChanged();
printf("\n\nSun Says Good %s !!!",objSun.GetStateName());
// inform that state has been changed
objSun.StateChanged();
printf("\n\nSun Says Good %s !!!",objSun.GetStateName());
// inform that state has been changed
objSun.StateChanged();	
printf("\n\nSun Says Good %s !!!",objSun.GetStateName());
Inside the interface,the following things are happening

// Handles the state change
void CSun::StateChanged()
{
    if (m_pState)
    {
        // Getting Next State
        CBaseState* pState = m_pState->GetNextState();
        // de allocates the memory
        delete m_pState;
          m_pState = pState;
    }
}

Defining Next State

On calling the GetNextState virtual function depends on the object each object will return its next state.
Morning object’s next state

CBaseState* CMorning::GetNextState()
{
    return new CEvening;
}
Evening object’s next state
CBaseState* CEvening::GetNextState()
{
    return new CNight;
}
Night object’s next state
CBaseState* CNight::GetNextState()
{
    return new CMorning;
}

What about this code

The above described code is a very basic level implementation of state Pattern. You can add more interfaces for your class to manage the state (e.g. setting and getting state) and improve the code with a good memory handling strategy.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sarath.


My Name is Sarath. Basically I'm from from Thrissur,Kerala, now living at Trivandum, Kerala.
Here I'm working as software engineer at Network System Technologies Pvt. Ltd (NeST).

Occupation: Software Developer
Company: NeST
Location: India India

Other popular Design and Architecture articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 15 of 15 (Total in Forum: 15) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralIssues.memberDealsBrokeMe12:21 8 Nov '06  
GeneralGood Work !member*Dreamz20:45 3 Jul '06  
GeneralRe: Good Work !memberSarath.4:03 4 Jul '06  
Generalwhat about many conditional transitions ?memberlecerf23:22 11 Jun '06  
GeneralRe: what about many conditional transitions ?memberSaRath C18:28 14 Jun '06  
GeneralFSM designsmemberLeonti6:20 6 Jun '06  
GeneralRe: FSM designsmemberLeonti6:38 6 Jun '06  
GeneralRe: FSM designsmemberSaRath C21:58 6 Jun '06  
GeneralRe: FSM designsmemberDealsBrokeMe12:18 8 Nov '06  
GeneralCommentmemberjefito5:09 6 Jun '06  
GeneralRe: CommentmemberSaRath C22:08 6 Jun '06  
GeneralInteresting...memberJohn M. Drescher8:30 2 Jun '06  
GeneralRe: Interesting...memberSaRath C0:22 4 Jun '06  
GeneralWell donememberNicholas Butler7:33 2 Jun '06  
GeneralRe: Well donememberSaRath C0:23 4 Jun '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 25 Jun 2006
Editor:
Copyright 2006 by Sarath.
Everything else Copyright © CodeProject, 1999-2008
Web18 | Advertise on the Code Project