一、前言
自然界所有事物都有自己的存在状态,比如水有固态、液态、气态,三种不同的心态有着完全不一样的外在特性,我们将事物所处的某一种形态称为状态。
二、状态模式概念
状态模式也称对象的行为模式,是指一个对象在其内部状态发生改变时,它表现的行为和外在属性不一样,这个对象看上去像是改变了它的类型一样。
状态模式的核心是封装,其对应的类图如下所示:
从上图中,可以看出状态模式有三类角色:
- State:抽象状态角色。它是接口或抽象类,负责对象状态的定义,并封装环境角色以实现状态切换;
- StateX:具体的状态角色。每一个具体的状态必须完成两个职责,即本状态的行为管理及趋向状态的处理【就是本状态下要做的事情,以及本状态如何过渡到其它状态】
- Context:环境角色。它用来定义客户端需要的接口,并负责具体的状态切换。它是对状态的管理类,其升级形式就是“状态机”;
状态模式的优点
- 代码接口清晰。避免了过多的switch…case或者if…else语句的使用,使程序更加简洁,提高了系统的可维护性;
- 封装性非常好。这是状态模式的核心,状态变换放置到类的内部实现,外部调用无需知道状态的变换;
- 很好地体现了开闭原则和单一职责原则。每一个状态都是一个子类,要增加状态就增加一个子类即可,修改也只修改一个子类;
状态模式的缺点
- 若状态比较多时,子类就会比较多,会照成类膨胀;在实际项目中,对象的状态最好不要超过5个;
状态模式的应用场景
- 行为随状态改变而改变的场景。比如权限设计,人员的状态不同,即使执行相同的行为,结果也会不同,这种情况下需要考虑用状态模式;
- 在程序中有大量分支和条件判断时,可用状态模式让它通过扩展子类实现条件判断处理;
状态模式常用的代码结构:
#include<iostream>
using namespace std;
class Context;//类的前置声明
class State { //抽象状态
public:
virtual void do_something() = 0;
virtual void switch_state() = 0;
};
//==================================================
class StateA :public State { //具体状态
public:
StateA(Context *context) {
this->context = context;
}
void switch_state();
void do_something();
private:
Context *context;
};
//==================================================
class StateB :public State { //具体状态
public:
StateB(Context *context) {
this->context = context;
}
void switch_state();
void do_something();
private:
Context *context;
};
//==================================================
class Context { //上下文的实现
public:
Context() {
stateA = new StateA(this);
stateB = new StateB(this);
this->currentState = stateA;
}
void switch_state() {
currentState->switch_state();
}
void setState(State* state) {
this->currentState = state;
}
State* getStateA() {
return stateA;
}
State* getStateB() {
return stateB;
}
private:
State *stateA, *stateB, *currentState;
};
//==================================================
void StateA::switch_state() {
do_something();
this->context->setState(this->context->getStateB());//转换到B状态的特定写法
};
void StateA::do_something() {
cout << "已转换到状态B" << endl;
};
//==================================================
void StateB::switch_state() {
do_something();
this->context->setState(this->context->getStateA());//转换到B状态的特定写法
};
void StateB::do_something() {
cout << "已转换到状态A" << endl;
};
//==================================================
//主函数
int main() {
Context *context = new Context();
context->switch_state();
context->switch_state();
context->switch_state();
context->switch_state();
return 0;
}