Intent |
Motivation |
Applicability |
Structure |
Participants |
Collaborations
Consequences |
Implementation |
Sample Code |
Known Uses |
Related Patterns
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
Abstract representations for changes in state are to be created. For
example, consider a class TCPConnection that represents
different states of a network connection. The effect of a request
such as Open depends on the current state of the connection.
By creating an abstract TCPState class, subclasses can
define the state-specific behavior.

Use the state pattern in either of the following cases:

Consider a C++ model for a TCP connection. Start by defining the
TCPConnection class, which will provide an interface for
transmitting data and hadles requests to change state.
class TCPOctetStream;
class TCPState;
class TCPConnection {
public:
TCPConnection();
void ActiveOpen();
void PassiveOpen();
void Close();
void Send();
void Acknowledge();
void Synchronize();
void ProcessOctet( TCPOctetStream* )
private:
friend class TCPState;
void ChangeState( TCPState* );
private:
TCPState* _state;
};
TCPConnection keeps an instance of the TCPState
class in the _state member variable. The class
TCPState duplicates the state-changing interface of
TCPConnection.
class TCPState {
public:
virtual void Transmit( TCPConnection*, TCPOctetStream* );
virtual void ActiveOpen( TCPConnection* );
virtual void PassiveOpen( TCPConnection* );
virtual void Close( TCPConnection* );
virtual void Synchronize( TCPConnection* );
virtual void Acknowledge( TCPConnection* );
virtual void Send( TCPConnection* );
protected:
void ChangeState( TCPConnection*, TCPState* );
};
TCPConnection delegates all state-specific requests to its
TCPState instance. It also provides an operating for changing
this variable to a new TCPState. The constructor initializes
the object to the TCPClosed state.
TCPConnection::TCPConnection()
{ _state = TCPClosed::Instance(); }
void TCPConnection::ChangeState( TCPState *s )
{ _state = s; }
void TCPConnection::ActiveOpen()
{ _state->ActiveOpen(this); }
void TCPConnection::PassiveOpen()
{ _state->PassiveOpen(this); }
void TCPConnection::Close()
{ _state->Close(this); }
void TCPConnection::Acknowledge()
{ _state->Acknowledge(this); }
void TCPConnection::Synchronize()
{ _state->Synchronize(this); }
TCPState implements default behavior for all requests
delegated to it. It can change the state of a TCPConnection
with ChangeState(). It is declared a friend of
TCPConnection to give it privilaged access to this
operation.
void TCPState::Transmit( TCPConnection*, TCPOctetStream* ) {}
void TCPState::ActiveOpen( TCPConnection* ) {}
void TCPState::PassiveOpen( TCPConnection* ) {}
void TCPState::Close( TCPConnection* ) {}
void TCPState::Synchronize( TCPConnection* ) {}
void TCPState::ChangeState( TCPPConnection *t, TCPState *s )
{ t->ChangeState(s); }
Subclasses of TCPState implement state-specific behavior. A
TCP connection can be in many states: Established, Listening, Closed, etc.,
and there's a subclass of TCPState for each state. Consider
those three states.
class TCPEstablished : public TCPState {
public:
static TCPState* Instance();
virtual void Transmit( TCPConnection*, TCPOctetStream* );
virtual void Close( TCPConnection* );
};
class TCPListen : public TCPState {
public:
static TCPState* Instance();
virtual void Send( TCPConnection* );
// ...
};
class TCPClosed : public TCPState {
public:
static TCPState* Instance();
virtual void ActiveOpen( TCPConnection* );
virtual void PassiveOpen( TCPConnection* );
// ...
};
The subclasses maintain no local state, so they can be shared and only
one instance of each is required. The unique instance of each
TCPState subclass is obtained by the static
Instance() operation, thus making the class a Singleton.
Each subclass implements state-specific behavior for valid requests in the state:
void TCPClosed::ActiveOpen( TCPConnection *t ) {
// send SYN, receive SYN, ACK, etc.
ChangeState( t, TCPEstablished::Instance() );
}
void TCPClosed::PassiveOpen( TCPConnection *t ) {
ChangeState( t, TCPListen::Instance() );
}
void TCPEstablished::Close( TCPConnection *t ) {
// send FIN, receive ACK of FIN
ChangeState( t, TCPListen::Instance() );
}
void TCPEstablished::Transmit( TCPConnection *t, TCPOctetStream *o ) {
t->ProcessOctet( o );
}
void TCPListen::Send( TCPConnection *t ) {
// send SYN, receive SYN, ACK, etc.
ChangeState( t, TCPEstablished::Instance() );
}
After performing state-specific work, these operations call the
ChangeState() operation to change the state of the
TCPConnection. The TCPConnection itself doesn't
know a thing about the TCP connection protocol, it's the
TCPState subclasses that define each state transition and
action in TCP.
Consider the pressing of buttons on the CAVE wand. Currently, this is
done by using if statements to check for
CAVEBUTTON1, CAVEBUTTON2, and
CAVEBUTTON3. Implementing these into a State pattern allows
for extendibility should other devices be used the future.
The Flyweight pattern explains when and how State objects can be shared. State objects are often Singletons.
Sourced from Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, and Grady Booch, Addison-Wesley Publishing Company, 1994.