C++状态模式

/**
    《状态模式》
    状态模式是一种行为设计模式, 
    让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。

    状态模式与有限状态机的概念紧密相关。
    状态机通常由众多条件运算符(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();
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橙子砰砰枪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值