1.定义(目的)
实现状态和行为的分离。
2.使用场景
行为随着状态改变(key),行为实现中有较多if else或switch语句
3.类图
a.上图do1,do2,do3就是行为,state1,state2,state3就是行为。可以看到行为和状态分离了,增加状态满足开闭原则,但是增加行为不满足。
b. 状态模式和策略模式的类图类似,策略模式各个策略间是平等的没有联系的;而状态模式的各个状态是有关联的,比如state1的do1要调用state2的do1来实现,那么就需要在state中也维护一个context,如下:
void do() { context->setState(Context::State1); context->getState().do(); }
c.策略模式和状态模式的应用场景不同:策略模式是一个行为,有多种策略可以实现;状态模式是一个行为,在不同状态下得表现的不一样。
4. 优缺点
(2)优点
①简化逻辑。单独的类来封装一个状态的处理,代码结构化和意图更清晰。对于依赖状态的if-else的情况,每个if或else可以由一个状态来代表。
②分离状态和行为。客户端通过context公共接口修改状态,只需关心状态的切换,不用关心状态对应的处理。增加状态满足开闭原则,修改一个状态行为,不会影响其他状态的行为,符合职责单一原则。
③增强扩展性。行为的公共接口,使得拓展状态,只需增加一个状态类即可。
(2)缺点
子类膨胀,程序引入过多状态类。
增加行为,不符合开闭原则
代码转至https://www.cnblogs.com/5iedu/p/5637909.html
#include <iostream> #include <string> using namespace std; class Context; //前向声明 //********************(State接口)******************************** //抽象电梯状态 class LiftState { protected: Context* context; public: void setContext(Context* context) { this->context = context; } //电梯开启动作 virtual void open() = 0; //电梯关门动作 virtual void close() = 0; //电梯运行动作 virtual void run() = 0; //电梯停止动作 virtual void stop() = 0; }; //***********************Context环境类***************************** class Context { private: LiftState* liftState; public: static LiftState* openningState; static LiftState* closingState; static LiftState* runningState; static LiftState* stoppingState; LiftState& getLiftState() { return *liftState; } void setLiftState(LiftState* liftState) { this->liftState = liftState; //把当前的环境通知到各个实现类中 this->liftState->setContext(this); } void open() { liftState->open(); } void close() { liftState->close(); } void run() { liftState->run(); } void stop() { liftState->stop(); } }; //***************************ConcreteState类******************************** //开门状态 class OpenningState : public LiftState { public: //打开电梯门 void open() { cout << "电梯门开启..." << endl; } //开门状态下,可以按下“关门”按钮 void close() { //将当前状态修改为关门状态 context->setLiftState(Context::closingState); //关门 context->getLiftState().close(); } //开门状态下不能运行! void run() { //do nothing; } //开门状态下,按停止没效果 void stop() { //do nothing } }; //关门状态 class ClosingState : public LiftState { public: //打开电梯门 void open() { //将当前状态修改为开门状态 context->setLiftState(Context::openningState); context->getLiftState().open(); } //关门状态 void close() { cout << "电梯门关闭..." << endl; } //关门状态,可以按“运行”按钮 void run() { //将当前状态修改为运行状态 context->setLiftState(Context::runningState); context->getLiftState().run(); } //关门状态下,可以切换到停止状态 void stop() { //将当前状态修改为停止状态 context->setLiftState(Context::stoppingState); context->getLiftState().stop(); } }; //运行状态 class RunningState : public LiftState { public: //运行状态,按“开门”按钮没效课 void open() { //do nothing } //运行状态按“关门”按钮没效果 void close() { //do nothing; } //运行状态 void run() { cout << "电梯上下运行..." << endl; } //运行状态下,可按“停止” void stop() { //将当前状态修改为停止状态 context->setLiftState(Context::stoppingState); context->getLiftState().stop(); } }; //停止状态 class StoppingState : public LiftState { public: //停止状态,可以打开电梯门 void open() { //将当前状态修改为开门状态 context->setLiftState(Context::openningState); context->getLiftState().open(); } //停止状态下,可以按下“关门”按钮没效果 void close() { //do nothing } //关门状态,可以按“运行”按钮! void run() { //将当前状态修改为运行状态 context->setLiftState(Context::runningState); context->getLiftState().run(); } //开门状态下,按停止没效果 void stop() { cout << "电梯停止了..." << endl; } }; LiftState* Context::openningState = new OpenningState(); LiftState* Context::closingState = new ClosingState(); LiftState* Context::runningState = new RunningState(); LiftState* Context::stoppingState = new StoppingState(); int main() { Context context; context.setLiftState(Context::closingState); context.open(); context.close(); context.run(); context.stop(); return 0; }