上海大型网站开发公司,株洲网站建设平台,大学生网站建设课程总结,网页传奇游戏怎么注销状态模式
如何去描述状态机#xff1f;
假设你需要实例化一台电梯#xff0c;并模仿出电梯的四个状态#xff1a;开启、关闭、运行、停止。也许你会这么写
class ILift{
public:virtual void open(){}virtual void close(){}virtual void run(){}virtual void stop(){}
}…状态模式
如何去描述状态机
假设你需要实例化一台电梯并模仿出电梯的四个状态开启、关闭、运行、停止。也许你会这么写
class ILift{
public:virtual void open(){}virtual void close(){}virtual void run(){}virtual void stop(){}
};
class Lift : public ILift{
public:void open(){ std::cout 电梯门关闭... std::endl; }void close(){ std::cout 电梯门开启... std::endl; }void run(){ std::cout 电梯上下跑起来... std::endl; }void stop(){ std::cout 电梯停止了... std::endl; }
};
int main(){ILift* lift new Lift();lift-open();lift-close();lift-run();lift-stop();
}
这样写未免太草率了。因为电梯在门开启的时候一般是不能运行的在运行的时候一般也不会门开启而在停止工作状态一般不会再去执行关门这个动作。所以需要设置一些状态去限制这台电梯的行为。于是在类Lift中存储电梯目前的状态在执行每个动作的时候用swith分支来判断当前动作是否有效以及更新当前状态。于是有了下面的代码 class ILift{
public:virtual void setState(int state){};virtual void open(){}virtual void close(){}virtual void run(){}virtual void stop(){}
};
class Lift : public ILift{
public:Lift(int state):state(state){}void setState(int state){ this-state state; }void close(){switch(state){case OPENING_STATE:closeWithoutLogic();setState(CLOSING_STATE);break;case CLOSING_STATE:break;case RUNNING_STATE:break;case STOPPING_STATE:break;}}void open(){switch(state){case OPENING_STATE:break;case CLOSING_STATE:openWithoutLogic();setState(OPENING_STATE);break;case RUNNING_STATE:break;case STOPPING_STATE:openWithoutLogic();setState(OPENING_STATE);}}void run(){switch(state){case OPENING_STATE:break;case CLOSING_STATE:runWithoutLogic();setState(RUNNING_STATE);break;case RUNNING_STATE:break;case STOPPING_STATE:runWithoutLogic();setState(RUNNING_STATE);}}void stop(){switch(state){case OPENING_STATE:break;case CLOSING_STATE:stopWithoutLogic();setState(STOPPING_STATE);break;case RUNNING_STATE:stopWithoutLogic();setState(STOPPING_STATE);break;case STOPPING_STATE:break;}}void closeWithoutLogic(){ std::cout 电梯门关闭... std::endl; }void openWithoutLogic() { std::cout 电梯门开启... std::endl; }void runWithoutLogic() { std::cout 电梯上下跑起来... std::endl; }void stopWithoutLogic() { std::cout 电梯停止了... std::endl; }
private:int state;
};
int main(){ILift* lift new Lift(STATE(OPENING_STATE));lift-close(); // 关闭lift-open(); // 开启lift-run(); // 无动作lift-stop(); // 无动作lift-close(); // 关闭
}
这个类的实现代码特别长内部包含了太多的switch语句。而且当需要增加状态时比如说电梯停电状态和电梯维修状态就需要去更改里面的switch语句。这样写违背了开闭原则以及单一性原则。为了在增加状态的时候尽量少的修改原有代码可以将swtich中的每个状态抽离出来单独包装成类。 创建context类在context类中存有LiftState对象用来记录当前的状态。此时context目前拥有四种状态对象用指针维护。每种状态的逻辑由各自类在内部实现。当电梯发生动作即context调用函数时函数内部会调用当前state对应的方法于是这部分逻辑转交由state内部实现。具体代码如下
#includeiostream
#includestringusing namespace std;class ContextBase;
class LiftState{
public:void setContext(ContextBase* context){ this-mContext context; }virtual void open(){}virtual void close(){}virtual void run(){}virtual void stop(){}ContextBase* getContext(){ return mContext; }
public:ContextBase* mContext;
};
class ContextBase{
public:ContextBase(){}virtual LiftState* getLiftState(){}virtual LiftState* getOpenningState(){}virtual LiftState* getClosingState(){}virtual LiftState* getRunningState(){}virtual LiftState* getStoppingState(){}virtual void setLiftState(LiftState* liftState){}virtual void open(){}virtual void close(){}virtual void run(){}virtual void stop(){}
public:LiftState* liftState;
};
class OpenningState : public LiftState{void open(){std::cout lift open... std::endl;}void close(){mContext-setLiftState(mContext-getClosingState());mContext-getLiftState()-close();}void run(){}void stop(){}
};
class ClosingState : public LiftState{void open(){mContext-setLiftState(mContext-getOpenningState());mContext-getLiftState()-open();}void close(){std::cout lift close... std::endl;}void run(){mContext-setLiftState(mContext-getRunningState());mContext-getLiftState()-run();}void stop(){mContext-setLiftState(mContext-getStoppingState());mContext-getLiftState()-stop();}
};
class RunningState : public LiftState{void open(){}void close(){}void run(){std::cout lift running... std::endl;}void stop(){mContext-setLiftState(mContext-getStoppingState());mContext-getLiftState()-stop();}
};
class StoppingState : public LiftState{void open(){mContext-setLiftState(mContext-getOpenningState());mContext-getLiftState()-open();}void close(){}void run(){mContext-setLiftState(mContext-getRunningState());mContext-getLiftState()-run();}void stop(){std::cout lift stopping... std::endl;}
};class Context : public ContextBase{
public:Context(){}LiftState* getLiftState(){return liftState;}LiftState* getOpenningState(){return openningState;}LiftState* getClosingState(){return closingState;}LiftState* getRunningState(){return runningState;}LiftState* getStoppingState(){return stoppingState;}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(); }
public:LiftState* openningState new OpenningState();LiftState* closingState new ClosingState();LiftState* runningState new RunningState();LiftState* stoppingState new StoppingState();
};int main(){Context* context new Context;context-setLiftState(new ClosingState());context-open();context-close();context-run();context-stop();
}
状态模式的优势
当由新的状态加入时只需要扩展子类而不需要过多地更改原有代码。遵守了开闭原则。
当动作和状态更新等逻辑交由状态类内部实现实现了单一性设计原则。
参考
Java设计模式——状态模式STATE PATTERN_java中state pattern-CSDN博客