状态模式C++详解
状态模式由来
面向对象设计其实就是希望做到代码的责任分解(也就是说,将状态设计成类,将责任分离,这个状态应该干嘛干嘛这样)。
状态模式: 当一个对象的内在状态改变的时候,允许其改变行为。
状态模式主要解决的是当控制一个对象状态转移的表达式过于复杂的时候,将状态的判断逻辑转移到表示不同状态的一系列的类当中,可以把复杂的判断逻辑简单化
状态模式c++实现
Context.h
#ifndef CONTEXT_H_
#define CONTEXT_H_
class State; // 声明,相当于外部符号
/*
这里告诉我们声明是声明,定义是定义,声明只是告诉你这里有,但是不一定在这里定义
*/
class Context {
public:
Context(State* s);
void Request();
void ChageState(State* s);
private:
State* state_;
};
#endif
Context.cc
#include "Context.h"
#include "State.h" // 如果不包含这个头文件就没有定义,这里也是声明有个class State 定义在State.o中
Context::Context(State* s) { state_ = s; }
void Context::Request() {
state_->Handle(this); // 修改状态并进行该状态下应有的操作
}
void Context::ChageState(State* s) {
delete state_; // 清楚之前的状态4
state_ = nullptr;
state_ = s;
}
状态抽象类
State.h
#ifndef STATE_H_
#define STATE_H_
#include <iostream>
#include "Context.h"
class State {
public:
virtual void Handle(Context* con) = 0;
};
#endif
具体状态类
Sleep.h
#ifndef SLEEP_H_
#define SLEEP_H_
#include "State.h"
#include "eat.h"
// 开始睡觉时候的状态
class Sleep : public State {
public:
void Handle(Context* con);
private:
};
#endif
Sleep.cc
#include "Sleep.h"
void Sleep::Handle(Context* con) {
std::cout << "现在的状态是睡觉" << std::endl;
std::cout << "睡醒啦该去吃饭了" << std::endl;
State* new_state = new Eat();
con->ChageState(new_state); // 状态动作的转移放置在状态里面
}
eat.h
#ifndef EAT_H_
#define EAT_H_
#include "Sleep.h"
#include "run.h"
// 开始睡觉时候的状态
class Eat : public State {
public:
void Handle(Context* con);
private:
};
#endif
eat.cc
#include "eat.h"
void Eat::Handle(Context* con) {
std::cout << "现在的状态是吃饭" << std::endl;
std::cout << "吃完饭该去运动了" << std::endl;
State* new_state = new Run();
con->ChageState(new_state); // 状态动作的转移放置在状态里面
}
run.h
#ifndef RUN_H_
#define RUN_H_
#include "Sleep.h"
#include "State.h"
// 开始睡觉时候的状态
class Run : public State {
public:
void Handle(Context* con);
private:
};
#endif
run.cc
#include "run.h"
void Run::Handle(Context* con) {
std::cout << "现在的状态是运动" << std::endl;
std::cout << "运动完该去睡觉了" << std::endl;
State* new_state = new Sleep();
con->ChageState(new_state); // 状态动作的转移放置在状态里面
}
main.cc
#include "Context.h"
#include "Sleep.h"
#include "State.h"
#include "eat.h"
#include "run.h"
int main() {
// 初始状态
State* s = new Sleep();
Context context(s);
context.Request();
context.Request();
context.Request();
context.Request();
context.Request();
}
运行结果如下
现在的状态是睡觉
睡醒啦该去吃饭了
现在的状态是吃饭
吃完饭该去运动了
现在的状态是运动
运动完该去睡觉了
现在的状态是睡觉
睡醒啦该去吃饭了
现在的状态是吃饭
吃完饭该去运动了