本文是对于 《设计模式 可复用面向对象软件的基础 Erich Gamma、Richard Helm》一书中的状态模型例子进行实现,并做了一些说明
引目:
考虑一个表示网络连接的类T C P C o n n e c t i o n。一个T C P C o n n e c t i o n对象的状态处于若干不同状态之一: 连接已建立( E s t a b l i s h e d)、正在监听( L i s t e n i n g )、连接已关闭( C l o s e d )。当一个T C P C o n n e c t i o n对象收到其他对象的请求时, 它根据自身的当前状态作出不同的反应。例如,一个O p e n请求的结果依赖于该连接是处于连接已关闭状态还是连接已建立状态。S t a t e模式描述了T C P C o n n e c t i o n如何在每一种状态下表现出不同的行为。这一模式的关键思想是引入了一个称为T C P S t a t e的抽象类来表示网络的连接状态。T C P S t a t e类为各表示不同的操作状态的子类声明了一个公共接口。T C P S t a t e的子类实现与特定状态相关的行为。例如, TCPEstablished和T C P C l o s e d类分别实现了特定于T C P C o n n e c t i o n的连接已建立状态和连接已关闭状态的行为。
T C P C o n n e c t i o n类维护一个表示T C P连接当前状态的状态对象(一个T C P S t a t e子类的实例)。T C P C o n n e c t i o n类将所有与状态相关的请求委托给这个状态对象。T C P C o n n e c t i o n使用它的T C P S t a t e子类实例来执行特定于连接状态的操作。一旦连接状态改变, T C P C o n n e c t i o n对象就会改变它所使用的状态对象。例如当连接从已建立状态转为已关闭状态时, TCPConnection 会用一个T C P C l o s e d的实例来代替原来的T C P E s t a b l i s h e d的实例。
状态模型的设计结构如下:
示例的实现
1 ) 谁定义状态转换S t a t e模式不指定哪一个参与者定义状态转换准则。如果该准则是固定的, 那么它们可在C o n t e x t中完全实现。然而若让S t a t e子类自身指定它们的后继状态以及何时进行转换, 通常更灵活更合适。这需要C o n t e x t增加一个接口, 让S t a t e对象显式地设定C o n t e x t的当前状态。
2) 基于表的另一种方法在C++ Programming Style[Car92]中, Carg i l描述了另一种将结构加载在状态驱动的代码上的方法: 他使用表将输入映射到状态转换。对每一个状态, 一张表将每一个可能的输入映射到一个后继状态。实际上, 这种方法将条件代码(和S t a t e模式下的虚函数)映射为一个查找表。
3 ) 创建和销毁S t a t e对象一个常见的值得考虑的实现上的权衡是, 究竟是( 1 )仅当需要S t a t e对象时才创建它们并随后销毁它们,还是( 2 )提前创建它们并且始终不销毁它们。
4 ) 使用动态继承改变一个响应特定请求的行为可以用在运行时刻改变这个对象的类的
办法实现, 但这在大多数面向对象程序设计语言中都是不可能的。
代码示例
代码是自己照着题意写的,可能有的 地方不怎么规范,但基本思想已明确,下是完整的代码,仅供参考与学习
#include <iostream>
enum {
S_CLOSE,
S_ESTABLISH,
S_LISTE
};
class TCPConnection;
class TCPEstablished;
class TCPClosed ;
class TCPState{
public:
virtual int ActiveOpen(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}
virtual int PassiveOpen(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}
virtual int Connect(TCPConnection *tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}
virtual int Close(TCPConnection * tcp){std::cout <<"some thing must be wrong"<<std::endl;return 0;}
virtual int Acknoledge(TCPConnection * tcp){std::cout <<"this type is :"<<_curStatu<<" 0:S_CLOSE,1:S_ESTABLISH,2:S_LISTE "<<std::endl; return 0;}
virtual int ChageState(TCPConnection * tcp,TCPState * s);
public:
virtual ~TCPState(){};
protected:
int _curStatu ;
};
class TCPEstablished:public TCPState{
public:
int Close(TCPConnection * tcp);
static TCPState* Instance() ;
};
class TCPListen:public TCPState{
public:
virtual int Connect(TCPConnection *tcp);
virtual int Close(TCPConnection * tcp);
static TCPState* Instance() ;
};
class TCPClosed:public TCPState{
public:
int PassiveOpen(TCPConnection *tcp);
virtual int ActiveOpen(TCPConnection *tcp);
static TCPState* Instance();
};
class TCPConnection{
private:
TCPState * state ;
public:
int Init();
int ActiveOpen();
int PassiveOpen();
int Connect();
int Close() ;
int Acknoledge();
int ChageState(TCPState * s);
};
/defines of method for TCPState /
int TCPState::ChageState(TCPConnection * tcp,TCPState * s){
tcp->ChageState(s);
return 0;
}
defines of method for classes inherited TCPState/
int TCPEstablished::Close(TCPConnection * tcp){
std::cout << "change status :Established ---> Close"<<std::endl;
tcp->ChageState(TCPClosed::Instance());
return 0;
}
TCPState* TCPEstablished::Instance(){
return new TCPEstablished ;
}
int TCPListen::Connect(TCPConnection *tcp){
std::cout << "change status :Listen ---> Established"<<std::endl;
tcp->ChageState(TCPEstablished::Instance());
return 0;
}
int TCPListen::Close(TCPConnection * tcp){
std::cout << "change status :Listen ---> Close"<<std::endl;
tcp->ChageState(TCPClosed::Instance());
return 0;
}
TCPState * TCPListen::Instance(){
return new TCPListen ;
}
int TCPClosed::ActiveOpen(TCPConnection *tcp){
std::cout << "change status :Close ---> Established"<<std::endl;
tcp->ChageState(TCPEstablished::Instance());
return 0;
}
int TCPClosed::PassiveOpen(TCPConnection *tcp){
std::cout << "change status :Close ---> Lisen"<<std::endl;
tcp->ChageState(TCPListen::Instance());
return 0;
}
TCPState * TCPClosed::Instance(){
return new TCPClosed ;
}
//TCPConnection///
int TCPConnection::Init(){
state = TCPClosed::Instance();
return 0;
}
int TCPConnection::ActiveOpen(){
state->ActiveOpen(this);
return 0;
}
int TCPConnection::PassiveOpen(){
state->PassiveOpen(this) ;
return 0;
}
int TCPConnection::ChageState(TCPState * s){
if(!state)
delete state ;
state = s ;
return 0;
}
int TCPConnection::Connect(){
state->Connect(this) ;
return 0;
}
int TCPConnection::Close() {
state->Close(this);
return 0;
}
int main(int arg,char ** argc){
TCPConnection t ;
t.Init();
t.ActiveOpen();
t.Close();
t.PassiveOpen();
t.ActiveOpen();
t.Close();
}
小结