定义:
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。(状态的变更引起了行为的变更,从外部看起来好像这个对象对应的类发生了改变一样)
State 抽象状态角色
接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。
ConcreteState 具体状态角色
每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,即本状态要做的事情,以及本状态如何过度到其他状态。
Context 环境角色
定义客户端需要的接口,并且负责具体状态的切换。
#include
#include
class Context;
//抽象环境角色
class State
{
public:
void setContext(Context &context)
{
this->m_context = &context;
}
virtual void handle1() = 0;
virtual void handle2() = 0;
protected:
Context *m_context;
};
//具体环境角色
class Context
{
public:
State* getCurrentState()
{
return this->m_curState;
}
void setCurrentState(State* state)
{
this->m_curState = state;
this->m_curState->setContext(*this);
}
void handle1()
{
this->m_curState->handle1();
}
void handle2()
{
this->m_curState->handle2();
}
public:
static State* m_state1;
static State* m_state2;
private:
State* m_curState;
};
//环境角色
class State1:public State
{
public:
virtual void handle1()
{
qDebug() << "this is handle1";
}
virtual void handle2()
{
this->m_context->setCurrentState(this->m_context->m_state2);
this->m_context->handle2();
}
};
class State2:public State
{
public:
virtual void handle1()
{
this->m_context->setCurrentState(this->m_context->m_state1);
this->m_context->handle1();
}
virtual void handle2()
{
qDebug() << "this is handle2";
}
};
State* Context::m_state1 = new State1();
State* Context::m_state2 = new State2();
int main()
{
Context context;
State* state1 = new State1();
context.setCurrentState(state1);
context.handle1();
context.handle2();
delete state1;
return 0;
}
//电梯接口
class ILift
{
public:
virtual void open() = 0;
virtual void close() = 0;
virtual void run() = 0;
virtual void stop() = 0;
virtual void setState(int state) = 0;
public:
static const int OPENING_STATE = 1;
static const int CLOSING_STATE = 2;
static const int RUNNING_STATE = 3;
static const int STOPPING_STATE = 4;
};
//电梯实现
class Lift:public ILift
{
public:
virtual void open()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->openWithoutLogic();
this->setState(OPENING_STATE);
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
this->openWithoutLogic();
this->setState(OPENING_STATE);
break;
}
}
virtual void close()
{
switch(this->m_state)
{
case OPENING_STATE:
this->closeWithoutLogic();
this->setState(CLOSING_STATE);
break;
case CLOSING_STATE:
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
break;
}
}
virtual void run()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->runWithoutLogic();
this->setState(RUNNING_STATE);
break;
case RUNNING_STATE:
break;
case STOPPING_STATE:
this->runWithoutLogic();
this->setState(RUNNING_STATE);
break;
}
}
virtual void stop()
{
switch(this->m_state)
{
case OPENING_STATE:
break;
case CLOSING_STATE:
this->stopWithoutLogic();
this->setState(CLOSING_STATE);
break;
case RUNNING_STATE:
this->stopWithoutLogic();
this->setState(CLOSING_STATE);
break;
case STOPPING_STATE:
break;
}
}
virtual void setState(int state)
{
this->m_state = state;
}
private:
void closeWithoutLogic()
{
qDebug() << "close";
}
void openWithoutLogic()
{
qDebug() << "open";
}
void runWithoutLogic()
{
qDebug() << "run";
}
void stopWithoutLogic()
{
qDebug() << "stop";
}
private:
int m_state;
};
int main()
{
ILift *lift = new Lift();
lift->setState(ILift::STOPPING_STATE);
lift->open();
lift->close();
lift->run();
lift->stop();
delete lift;
return 0;
}
电梯实现类Lift有点长。里面使用了大量的switch...case,在业务复杂的情况下,程序会更长。
扩展性非常差。电梯还有通电和断点两个状态,若要增加这两个方法,原有4个方法都需要增加判断条件
非常规状态无法实现。
/ ******************************************* 声明 ********************************* ///
class LiftState;
//上下文类 声明
class Context
{
public:
Context();
LiftState* getLiftState();
void setLiftState(LiftState *liftState);
void open();
void close();
void run();
void stop();
public:
static LiftState *m_openningState;
static LiftState *m_closingState;
static LiftState *m_runningState;
static LiftState *m_stoppingState;
private:
LiftState *m_liftState;
};
//抽象电梯状态 声明
class LiftState
{
public:
void setContext(Context &context);
virtual void open() = 0;
virtual void close() = 0;
virtual void run() = 0;
virtual void stop() = 0;
protected:
Context *m_context;
};
//关闭状态 声明
class ClosingState:public LiftState
{
public:
virtual void open();
virtual void close();
virtual void run();
virtual void stop();
};
//敞门状态 声明
class OpenningState:public LiftState
{
public:
virtual void open();
virtual void close();
virtual void run();
virtual void stop();
};
//运行状态 声明
class RunningState:public LiftState
{
public:
virtual void open();
virtual void close();
virtual void run();
virtual void stop();
};
//停止状态 声明
class StoppingState:public LiftState
{
public:
virtual void open();
virtual void close();
virtual void run();
virtual void stop();
};
/// *********************************************** 定义 ************************************************* ///
//上下文类 定义
LiftState* Context::m_openningState = new OpenningState();
LiftState* Context::m_closingState = new ClosingState();
LiftState* Context::m_runningState = new RunningState();
LiftState* Context::m_stoppingState = new StoppingState();
Context::Context()
{
this->setLiftState(this->m_closingState);
}
LiftState* Context::getLiftState()
{
return this->m_liftState;
}
void Context::setLiftState(LiftState* liftState)
{
this->m_liftState = liftState;
this->m_liftState->setContext(*this);
}
void Context::open()
{
this->m_liftState->open();
}
void Context::close()
{
this->m_liftState->close();
}
void Context::run()
{
this->m_liftState->run();
}
void Context::stop()
{
this->m_liftState->stop();
}
//抽象电梯状态 定义
void LiftState::setContext(Context &context)
{
this->m_context = &context;
}
//关闭状态 定义
void ClosingState::open()
{
this->m_context->setLiftState(m_context->m_openningState);
this->m_context->getLiftState()->open();
}
void ClosingState::close()
{
qDebug() << "close";
}
void ClosingState::run()
{
this->m_context->setLiftState(m_context->m_runningState);
this->m_context->getLiftState()->run();
}
void ClosingState::stop()
{
this->m_context->setLiftState(m_context->m_stoppingState);
this->m_context->getLiftState()->stop();
}
//敞门状态 定义
void OpenningState::open()
{
qDebug() << "open";
}
void OpenningState::close()
{
this->m_context->setLiftState(m_context->m_closingState);
this->m_context->getLiftState()->close();
}
void OpenningState::run(){}
void OpenningState::stop(){}
//运行状态 定义
void RunningState::open(){}
void RunningState::close(){}
void RunningState::run()
{
qDebug() << "run";
}
void RunningState::stop()
{
this->m_context->setLiftState(m_context->m_stoppingState);
this->m_context->getLiftState()->stop();
}
//停止状态 定义
void StoppingState::open()
{
this->m_context->setLiftState(m_context->m_openningState);
this->m_context->getLiftState()->open();
}
void StoppingState::close(){}
void StoppingState::run()
{
this->m_context->setLiftState(m_context->m_runningState);
this->m_context->getLiftState()->run();
}
void StoppingState::stop()
{
qDebug() << "stop";
}
int main()
{
Context context;
context.open();
context.close();
context.run();
context.stop();
return 0;
}
子类会太多,也就是类膨胀。如果完全使用状态模式就会有太多的子类,不好管理,需要在项目中自己衡量。有很多方式可以解决这个状态问题,如在数据库中建立一个状态表,然后根据状态执行响应的操作。
状态模式适用于当前某个对象在它的状态发生改变时,它的行为也随着发生比较大的变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的状态最好不要超过5个。
参考文献《秦小波. 设计模式之禅》(第2版) (华章原创精品) 机械工业出版社