状态模式
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。它有两种使用情况:(1)一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。(2)一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。比如一个你和心爱的那个
动机
在软件构建过程中,某些对象的状态如果改变,其行为也随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同;如何在运行时候根据对象的 状态来透明的更改对象的行为,而不会为对象操作和状态转化之间引入紧耦合
角色扮演
抽象状态(State)
定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态(XXState)
每一个子类实现一个
环境(Context)
表示各种状态的对象和一个行为随着状态对象改变而改变的对象
举例说明
比如qq会员,各种会员类型,黄砖、黑砖、绿砖、红砖、紫砖、粉砖,不同会员标识,可享受不同的待遇和福利,可以拥有不同的权利,干不同的事。
#ifndef STATE_H
#define STATE_H
#include <iostream>
using namespace std;
class State;
class Context
{
public:
Context(State* state){this->m_state = state;}
virtual ~Context(){}
void request();
void setState(State* state){
if(m_state != NULL)
delete m_state;
m_state = state;
}
protected:
private:
State * m_state;
};
class State
{
public:
State(){}
virtual ~State(){}
virtual void handle(Context*) = 0;
protected:
private:
};
class RealState1 : public State
{
public:
RealState1(){}
virtual ~RealState1(){}
void handle(Context* pContext){
cout << "黄钻---空间用的"<<endl;
}
protected:
private:
};
class RealState2 : public State
{
public:
RealState2(){}
virtual ~RealState2(){}
void handle(Context* pContext){
cout << "紫钻----在游戏内可以获得踢人和防止被踢的权利" <<endl;
}
protected:
private:
};
demo:
int main(){
Context * conn1 = new Context(new RealState1());
Context * conn2 = new Context(new RealState2());
conn1->request();
conn2->request();
return 0;
}
结果:
优点
在对象的行动取决于本身的状态时,可以适用于状态模式,免去了过多的if–else判断,这对于一些复杂的和繁琐的判断逻辑有很好的帮助
缺点
但是使用状态模式,势必会造成更多的接口和类,对于非常简单的状态判断,可以不使用。
应用场景
(1)对象的行为依赖于它的状态,并且可以在运行时根据状态改变行为。
(2)代码中包含大量与对象状态有关的if/else语句,这些条件对应于对象的各种状态,这些冗余条件语句的出现导致代码的可维护性和灵活性变差,这种情况适合使用状态模式进行优化。