状态模式
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
(当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。)
通用类图
抽象状态类
抽象类,负责对象状态定义,并且封装环境角色以实现状态切换
具体状态类
继承抽象类,完成两个职责,本状态的行为管理以及趋向状态处理
环境类
定义客户端需要的接口,负责具体状态的切换
通用源码
//抽象状态类
class State {
protected:
//定义一个环境类,提供子类访问
Context* context;
public:
//设置环境类
void setContext(Context* c) { context = c; }
//具有的行为
virtual void handle1() = 0;
virtual void handle2() = 0;
};
//具体状态类
class ConcreteState1 : public State {
public:
//本状态的处理逻辑
void handle1() override {
//do something
}
//切换到状态2
void handle2() override {
context->setCurrentState(Context::state2);
context->handle2();
}
};
class ConcreteState2 : public State {
public:
void handle2() override {
//do something
}
void handle1() override {
context->setCurrentState(Context::state1);
context->handle1();
}
};
//环境类
class Context {
public:
//定义状态
static State* state1;
static State* state2;
//获得当前状态
State* getCurrentState() { return currentState; }
//设置当前状态
void setCurrentState(State* s) {
currentState = c;
//切换状态
currentState->setContext(this);
}
//行为委托
void handle1() { currentState->handle1(); }
void handle2() { currentState->handle2(); }
private:
//当前状态
State* currentState;
}
State* Context::state1 = new ConcreteState1();
State* Context::state2 = new ConcreteState2();
优点
结构清晰
遵循设计原则
封装性非常好
缺点
子类会非常多
使用场景
行为随状态改变而改变的场景
条件、分支判断语句的替代者
示例代码
#include <iostream>
#include <string>
using namespace std;
class Context;
class LiftState {
public:
void setContext(Context* c) { context = c; }
virtual void open() = 0;
virtual void close() = 0;
virtual void run() = 0;
virtual void stop() = 0;
protected:
Context* context;
};
class OpenningState;
class ClosingState;
class RunningState;
class StoppingState;
class Context {
private:
LiftState *liftState;
public:
LiftState* getLiftState() {
return liftState;
}
void setLiftState(LiftState* l) {
liftState = l;
liftState->setContext(this);
}
void open() {
liftState->open();
}
void close() {
liftState->close();
}
void run() {
liftState->run();
}
void stop() {
liftState->stop();
}
static OpenningState* openningState;
static ClosingState* closingState;
static RunningState* runningState;
static StoppingState* stoppingState;
};
class OpenningState : public LiftState {
public:
void open() override {
cout << "open lift..." << endl;
}
void close() override;
void run() override {
}
void stop() override {
}
};
class ClosingState : public LiftState {
public:
void open() override {
context->setLiftState(Context::openningState);
context->getLiftState()->open();
}
void close() override {
cout << "close lift..." << endl;
}
void run() override;
void stop() override;
};
class RunningState : public LiftState {
public:
void open() override {
}
void close() override {
}
void run() override {
cout << "run lift..." << endl;
}
void stop() override;
};
class StoppingState : public LiftState {
public:
void open() override {
context->setLiftState(Context::openningState);
context->getLiftState()->open();
}
void close() override {
}
void run() override {
context->setLiftState(Context::runningState);
context->getLiftState()->run();
}
void stop() override {
cout << "stop lift..." << endl;
}
};
OpenningState* Context::openningState = new OpenningState();
ClosingState* Context::closingState = new ClosingState();
RunningState* Context::runningState = new RunningState();
StoppingState* Context::stoppingState = new StoppingState();
void OpenningState::close() {
context->setLiftState(Context::closingState);
context->getLiftState()->close();
}
void ClosingState::run() {
context->setLiftState(Context::runningState);
context->getLiftState()->run();
}
void ClosingState::stop() {
context->setLiftState(Context::stoppingState);
context->getLiftState()->stop();
}
void RunningState::stop() {
context->setLiftState(Context::stoppingState);
context->getLiftState()->stop();
}
int main() {
Context* c = new Context();
c->setLiftState(new ClosingState());
c->open();
c->close();
c->run();
c->stop();
return 0;
}