状态,应该大家都很熟,学过计算机的应该都知道状态机。
状态实现比较简单,当然也比较灵活。写一个demo程序,测试一下而已,主要是状态和策略两个模式很相似,想体会一下其中的区别。
状态一般也要求状态是一个单例,否则状态的生成和回收还是比较繁琐的。
1. State.h:
#include <iostream>
using namespace std;
class Context;
class State{
public:
State(){}
~State(){};
virtual int Handle(Context * ctxt) = 0;
};
class Context{
public:
Context(){
state = NULL;
}
int Handle(){
if (state){
state->Handle(this);
} else {
cout<<"NULL state!"<<endl;
}
return 0;
}
int change_state(State * new_state){
state = new_state;
return 0;
}
private:
State * state;
};
2. StateA.h/StateA.cpp
#ifndef __STATEA_H_
#define __STATEA_H_
#include "State.h"
#include "StateB.h"
class StateA : public State{
public:
static StateA * Instance();
int Handle(Context * ctxt);
~StateA(){}
private:
StateA(){}
static StateA * instance;
};
#endif //__STATEA_H_
#include "StateA.h"
class StateB;
StateA * StateA::instance = NULL;
StateA * StateA::Instance(){
if (!instance){
instance = new StateA();
}
return instance;
}
int StateA::Handle(Context * ctxt){
cout<<"handle state A: A=>B!"<<endl;
ctxt->change_state(StateB::Instance());
return 0;
}
3. StateB.h/.cpp
#ifndef __STATEB_H_
#define __STATEB_H_
#include "State.h"
#include "StateA.h"
class StateB : public State{
public:
~StateB(){}
static StateB * Instance();
int Handle(Context * ctxt);
private:
StateB(){}
static StateB * instance;
};
#endif //__STATEB_H_
#include "StateB.h"
StateB * StateB::instance = NULL;
StateB * StateB::Instance(){
if (!instance){
instance = new StateB();
}
return instance;
}
int StateB::Handle(Context * ctxt){
cout<<"handle state B: B=>A!"<<endl;
ctxt->change_state(StateA::Instance());
return 0;
}
4. test
#include <iostream>
#include "StateA.h"
#include "StateB.h"
using namespace std;
int main(){
Context * ctxt = new Context();
ctxt->change_state(StateA::Instance());
ctxt->Handle();
ctxt->Handle();
ctxt->Handle();
return 0;
}
这里为了写个测试程序还搞了很多*.h*.cpp文件,主要是因为交叉包含问题。这个感觉很挫,不知道新的编译器或者标准有没有改进。
总结,state模式比较简单,使用场合也比较明确。很多时候都不需要抽象出具体的state,直接通过应用场景相关的类代替即可,因为,问题的关键不是模板,而是不同状态下的动作和状态转移关系。
另外,context要暴露状态转换接口方式有点繁琐,感觉也比较危险。但是还没想到有什么好的解决方案。