状态模式的意图就是当一个对象的内部状态发生改变时也改变了它的行为!
比如一个小孩,身体健康的时候,可以出去和小伙伴一起玩耍,一起去幼儿园,但生病的时候,只能在家休息,吃药等!同样是小孩的行为,当小孩的健康状态的不同,其行为的执行结果就发生变化了!
把上面这个例子用程序实现时,就是小孩这个对象,在健康状态由健康到生病时,这个小孩的某个行为,比如说:自由活动(),则由出去和小伙伴玩耍,变成到躺在床上吃药休息!
当然在实现这个例子的时候,其自由活动()这个行为有小孩对象抽象出来,有一个专门的状态类来实施这个行为!可以避免在小孩对象中的多重判断语句,并且如果出现一个新的状态,也不需要去修改先前的设置,坚持了"开放封闭"原则,而且也不需要小孩对象来判断什么状态来执行什么行为,坚持了"单一职责"原则!
具体的结构图不复杂,一个是上下文角色,另一个就是具体状态角色,它们都是从抽象的状态接口继承行为并实现!
上例中的小孩就是个上下文角色,状态角色就是小孩的健康状况,状态角色的行为就是小孩的"自由活动()",小孩的角色里有引用抽象状态,通过外界判断小孩的健康状态并确定,小孩的行为就发生相应的变化!(假设小孩的健康状态是由医生来判断的,并影响了小孩的具体行为,虽然在实际生活中,这个是小孩的主观状态和主观行为)
这个模式的适用情景有如下2个方面:
1)一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2)一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。S t a t e模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
在使用这个模式的时候,会涉及到哪个角色来决定状态转换,GOF没有限制,我们可根据实际情况,如果状态在我们的掌握之中,不会再发生什么变化(呵呵,这个情况一般比较少,程序都是会变化的),可以让Context(上下文角色)来决定!当然,我们可以通过外界来为上下文角色传递状态,那就更好了,可以灵活应变各种变化,即使发生新的状态!
OK! 状态模式就说这么多了!
状态模式(State)允许一个对象在其内部状态改变的时候改变行为。结构图为:
汽车有不同的档速,当行车时,经常需要换档,换档是从低到高,换档的过程就是状态的改变过程。
实现代码:
class State;
class Car
{
public :
Car(State * );
virtual ~ Car();
void SetState(State * );
void Pull();
private :
State * m_pState;
};
#include " stdafx.h "
#include " Car.h "
#include " State.h "
#include < iostream >
using namespace std;
Car::Car(State * pState)
{
m_pState = pState;
cout << * m_pState;
}
Car:: ~ Car()
{
}
void Car::SetState(State * pState)
{
m_pState = pState;
cout << " 挂新档, " << * m_pState;
}
void Car::Pull()
{
m_pState -> ChangeState( this );
}
// State.h
#include < iostream >
#include " Car.h "
class State
{
public :
State( char * pName);
virtual ~ State();
virtual void ChangeState(Car * ) = 0 ;
friend std::ostream & operator << (std::ostream & os, State & state);
private :
char * m_pName;
};
// State.cpp
#include " stdafx.h "
#include " State.h "
using namespace std;
State::State( char * pName)
{
m_pName = pName;
}
State:: ~ State()
{
}
ostream & operator << (ostream & os, State & state)
{
return os << " 当前档位: " << state.m_pName << endl;
}
// Off.h
#include " State.h "
class Off : public State
{
public :
Off();
virtual ~ Off();
void ChangeState(Car * );
};
// Off.cpp
#include " stdafx.h "
#include " Off.h "
#include " Low.h "
#include < iostream >
using namespace std;
Off::Off() : State( " 空档 " )
{
}
Off:: ~ Off()
{
}
void Off::ChangeState(Car * pCar)
{
pCar -> SetState( new Low);
}
// Low.h
#include " State.h "
class Low : public State
{
public :
Low();
virtual ~ Low();
void ChangeState(Car * );
};
// Low.cpp
#include " stdafx.h "
#include " Low.h "
#include " Medium.h "
Low::Low() : State( " 低档 " )
{
}
Low:: ~ Low()
{
}
void Low::ChangeState(Car * pCar)
{
pCar -> SetState( new Medium);
}
// Medium.h
#include " State.h "
class Medium : public State
{
public :
Medium();
virtual ~ Medium();
void ChangeState(Car * );
};
// Medium.cpp
#include " stdafx.h "
#include " Medium.h "
#include " High.h "
Medium::Medium() : State( " 中档 " )
{
}
Medium:: ~ Medium()
{
}
void Medium::ChangeState(Car * pCar)
{
pCar -> SetState( new High);
}
// High.h
#include " State.h "
class High : public State
{
public :
High();
virtual ~ High();
void ChangeState(Car * );
};
// High.cpp
#include " stdafx.h "
#include " High.h "
#include " Off.h "
High::High() : State( " 高档 " )
{
}
High:: ~ High()
{
}
void High::ChangeState(Car * pCar)
{
pCar -> SetState( new Off);
}
// main.cpp
#include " stdafx.h "
#include " Car.h "
#include " Off.h "
int main( int argc, char * argv[])
{
State * pState = new Off;
Car * pCar = new Car(pState);
pCar -> Pull();
pCar -> Pull();
pCar -> Pull();
pCar -> Pull();
return 0 ;
}
最后输出:
当前档位:空档
挂新档,当前档位:低档
挂新档,当前档位:中档
挂新档,当前档位:高档
挂新档,当前档位:空档