[Home]  [Edit this page]  [Recent Changes]  [Special Pages]  [Help
CppState

(C++) State

A Design Pattern [1].

A State enables you to change a class its state. Instead of using internal type switching, you let polymorphism sort the State-dependent function out.

In this Design Pattern there are two players:
  • the Context
  • the State
The State is a member of the Context. When the state of the Context is changed, only the State is changed. The State has access to the Context, either with a pointer to the Context in every function or the State is a friend class of the Context, due to which it can access all the Context its member variables.

The State can be seen as an internal state-dependent switch, in which not the entire class changes to change its behaviour.

The State is related to the Strategy Design Pattern, except that Strategy does not have a pointer to its Context. Therefore, a State can only be used for one Context, whereas the Strategy can be used by multiple classes.

Below is a simple example. It describes a class with two member variables and two States. These States are 'plus' and 'minus'. It can change its state and then either adds or substracts these two numbers. In this example, the State is a friend class of its context, but this need not to be the case.

For an example of this same state seperated properly over multiple files, click here

  1. include <iostream>
  2. include <memory>
  3. include <cassert>
enum enumState{ plus, minus}; //--------------------------------------------------------------------------- // CLASS DECLARATION // (for in .H file) //--------------------------------------------------------------------------- class StateBase; //Forward declaration class StatePlus; //Forward declaration class StateMinus; //Forward declaration class Context { friend class StateBase; friend class StatePlus; friend class StateMinus; public: Context(); void setState(const enumState&); void doIt() const; private: std::auto_ptr<StateBase> mState; const int mValue1; const int mValue2; }; class StateBase { public: StateBase() {} //Empty constructor virtual int doIt() const = 0; protected: Context * mContext; //Pointer to the Context }; class StatePlus : public StateBase { public: StatePlus(Context *); //Can only initialize with Context pointer int doIt() const; }; class StateMinus : public StateBase { public: StateMinus(Context *); //Can only initialize with Context pointer int doIt() const; }; //--------------------------------------------------------------------------- // CLASS DEFINITION // (for in .CPP file) //--------------------------------------------------------------------------- Context::Context() : mState(new StatePlus(this)), //Initializes State mValue1(std::rand()%100), //Random number mValue2(std::rand()%100) //Random number { //Nothing } //--------------------------------------------------------------------------- void Context::setState(const enumState& state) { switch(state) { case plus : mState.reset(new StatePlus(this)); break; case minus: mState.reset(new StateMinus(this)); break; default: assert(!"Unknown state"); std::exit(1); //Use of assert to get line number } } //--------------------------------------------------------------------------- void Context::doIt() const { //The function doIt is delegated to the State //Therefore this function is State-dependent std::cout << "Doing it with " << mValue1 << " and " << mValue2 << ": " << mState->doIt() << std::endl; } //--------------------------------------------------------------------------- StatePlus::StatePlus(Context * context) { mContext = context; } //--------------------------------------------------------------------------- StateMinus::StateMinus(Context * context) { mContext = context; } //--------------------------------------------------------------------------- int StatePlus::doIt() const { //Adds the two values of Context return (mContext->mValue1 + mContext->mValue2); } //--------------------------------------------------------------------------- int StateMinus::doIt() const { //Adds the two values of Context return (mContext->mValue1 - mContext->mValue2); } //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { //Make a Context const std::auto_ptr<Context> myContext(new Context); //Set the State myContext->setState(plus); //Do the State-dependent function myContext->doIt(); //Set the State myContext->setState(minus); //Do the State-dependent function myContext->doIt(); //Program done }


Code links

State in other programming languages

  • (none on CodePedia yet)

References

1) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns. Publisher: Addison-Wesley Professional; 1st edition (January 15, 1995). ISBN: 0201633612

last edited (November 16, 2006) by bilderbikkel, Number of views: 4724, Current Rev: 16 (Diff)

[Edit this page]  [Page history]  [What links here]  [Discuss this topic]  [Printer Friendly]  

Members

Username:

Password:


Register
Forgot Password?




Programmers Heaven - for .NET, Java, C/C++ and WEB Developers!
© 1996-2008 Community Networks Ltd. All rights reserved. Reproduction in whole or in part, in any form or medium without express written permission is prohibited. Violators of this policy may be subject to legal action. Please read Terms Of Use and Privacy Statement for more information. Development by Tore Nestenius at .NET Consultant - Synchron Data.