/**
《状态模式》
状态模式是一种行为设计模式,
让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。
状态模式与有限状态机的概念紧密相关。
状态机通常由众多条件运算符(if或switch)实现,可根据对象的当前状态选择相应的行为。
当我们逐步在文档类中添加更多状态和依赖于状态的行为后,基于条件语句的状态机就会暴露其最大的弱点。
状态模式建议为对象的所有可能状态新建一个类, 然后将所有状态的对应行为抽取到这些类中。
如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
*/
#include <iostream>
#include <string>
#include <typeinfo>
// 上下文类和状态类两者相互引用
// 上下文类
class Context;
// 状态基类接口
class State
{
protected:
Context *context_; // 反向引用
public:
virtual ~State() {}
// 给状态设置上下文
void SetContext(Context *context)
{
this->context_ = context;
}
// 不同上下文对应的不同事件,也就是当前不同的状态,对应不同的行为
// 当有新的状态行为的时候,只需要增加新的Handle,并在子类里重写即可
virtual void Handle1() = 0;
virtual void Handle2() = 0;
};
// 上下文类
class Context
{
private:
State *state_; // 表示状态,状态和上下文状态对应
public:
// 设置当前的状态,这里的参数应是State的子类:具体的A状态或B状态
Context(State *state) : state_(nullptr)
{
this->TransitionTo(state); // 设置状态
}
~Context()
{
delete state_;
}
// 设置状态
void TransitionTo(State *state)
{
std::cout << "Context: Transition to " << typeid(*state).name() << std::endl;
// 如果有旧的状态,先释放掉旧的状态
if (this->state_ != nullptr)
{
delete this->state_;
}
// 设置新的状态
this->state_ = state;
// 将新的状态的上下文设置成当前上下文
// 必须要设置,不然在释放旧状态的时候就会释放空内存
// 必须相互引用,相互设置
this->state_->SetContext(this);
}
// 对状态的应答
void Request1()
{
this->state_->Handle1();
}
void Request2()
{
this->state_->Handle2();
}
};
// 将状态 变成 真实的类
class ConcreteStateB;
class ConcreteStateA : public State
{
public:
void Handle1() override;
void Handle2() override
{
std::cout << "ConcreteState A handles request2" << std::endl;
}
};
class ConcreteStateB : public State
{
public:
void Handle1() override
{
std::cout << "ConcreteStateB handles request2" << std::endl;
}
void Handle2() override
{
std::cout << "ConcreteStateB handles request2" << std::endl;
std::cout << "ConcreteStateB wangs to change the state of the context." << std::endl;
this->context_->TransitionTo(new ConcreteStateA);
}
};
void ConcreteStateA::Handle1()
{
std::cout << "ConcreteState A handles request1" << std::endl;
std::cout << "ConcreteState A wants to change the state of the context." << std::endl;
// 设置成状态B,函数内部自动析构掉状态A
this->context_->TransitionTo(new ConcreteStateB);
}
int main()
{
// 新建一个环境,是状态A
Context *context = new Context(new ConcreteStateA);
context->Request1();
// context->Request1();
context->Request2();
}
07-18
5410