1、意图
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
2、适应性
Use the State pattern in either of the following cases:
• An object's behavior depends on its state, and it must change itsbehavior at run-time depending on that state.
• Operations have large, multipart conditional statements that depend onthe object's state. This state is usually represented by one or moreenumerated constants. Often, several operations will contain thissame conditional structure. The State pattern puts
each branch of theconditional in a separate class. This lets you treat the object'sstate as an object in its own right that can vary independently fromother objects.
3、结构
4、示例代码
First, we define the class TCPConnection, which provides aninterface for transmitting data and handles 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;
};
The class TCPState duplicates the state-changing interface of TCPConnection. Each TCPState operation takes a TCPConnection instance as a parameter, letting TCPState access data from TCPConnection and change the connection's state.
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 itsTCPState instance _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 requestsdelegated to it. It can also change the state of a TCPConnection with the ChangeState operation.TCPState is declared a friend of TCPConnection togive it privileged 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 (TCPConnection* t, TCPState* s) {
t->ChangeState(s);
}
There's a subclass of TCPState for each state.We'll discuss three subclasses in detail: TCPEstablished,TCPListen, and TCPClosed.
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*);
// ...
};
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());
}