0. 简介

状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。这其实就有点类似算法中的有限状态机的形式。
在这里插入图片描述

其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。

1. 状态模式示意图

策略模式和状态模式两个模式很相似,区别就在于策略模式对象初始化的时候更改执行模式,而状态模式是根据对象实例的周期时间而动态地改变对象实例的执行模式。 所以当对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式。
在这里插入图片描述
上下文(Context):也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。

抽象状态(State):定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。

具体状态(Concrete State):实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

2. 示例代码

我们可以知道,状态模式在函数内部就自己包含有一套逻辑判断用于实现子类与子类之间的相互调用,从而影响数据流的走向,这也要求我们要对代码的流程和逻辑有充分的验证。
在这里插入图片描述

// 状态类基类
class War;
class State 
{
public:
    virtual void Prophase() {}
    virtual void Metaphase() {}
    virtual void Anaphase() {}
    virtual void End() {}
    virtual void CurrentState(War *war) {}
};
//战争
class War
{
private:
    State *m_state;  //目前状态
    int m_days;      //战争持续时间
public:
    War(State *state): m_state(state), m_days(0) {}
    ~War() { delete m_state; }
    int GetDays() { return m_days; }
    void SetDays(int days) { m_days = days; }
    void SetState(State *state) { delete m_state; m_state = state; }
    void GetState() { m_state->CurrentState(this); }
};

// 具体的状态类

//战争结束
class EndState: public State
{
public:
    void End(War *war) //结束阶段的具体行为
    {
        cout<<"战争结束"<<endl;
    }
    void CurrentState(War *war) { End(war); }
};
//后期
class AnaphaseState: public State
{
public:
    void Anaphase(War *war) //后期的具体行为
    {
        if(war->GetDays() < 30)
            cout<<"第"<<war->GetDays()<<"天:战争后期,双方拼死一搏"<<endl;
        else
        {
            war->SetState(new EndState());
            war->GetState();
        }
    }
    void CurrentState(War *war) { Anaphase(war); }
};
//中期
class MetaphaseState: public State
{
public:
    void Metaphase(War *war) //中期的具体行为
    {
        if(war->GetDays() < 20)
            cout<<"第"<<war->GetDays()<<"天:战争中期,进入相持阶段,双发各有损耗"<<endl;
        else
        {
            war->SetState(new AnaphaseState());
            war->GetState();
        }
    }
    void CurrentState(War *war) { Metaphase(war); }
};
//前期
class ProphaseState: public State
{
public:
    void Prophase(War *war)  //前期的具体行为
    {
        if(war->GetDays() < 10)
            cout<<"第"<<war->GetDays()<<"天:战争初期,双方你来我往,互相试探对方"<<endl;
        else
        {
            war->SetState(new MetaphaseState());
            war->GetState();
        }
    }
    void CurrentState(War *war) { Prophase(war); }
};

// 使用方式

//测试案例
int main()
{
    War *war = new War(new ProphaseState());
    for(int i = 1; i < 40;i += 5)
    {
        war->SetDays(i);
        war->GetState();
    }
    delete war;
    return 0;
}

3. 状态模式的优缺点

在这里插入图片描述
状态可被视为策略的扩展。 两者都基于组合机制: 它们都通过将部分工作委派给 “帮手” 对象来改变其在不同情景下的行为。 策略使得这些对象相互之间完全独立, 它们不知道其他对象的存在。 但状态模式没有限制具体状态之间的依赖, 且允许它们自行改变在不同情景下的状态

总的来说状态模式作为条件分之判断语句的替代者,其逻辑结构以及可扩展性是优于这些的,而且可以根据条件有效地转换行为,是一种比较优秀的操作模式

4. 参考链接

http://c.biancheng.net/view/1388.html

https://blog.csdn.net/wuzhekai1985/article/details/6675799

https://www.cnblogs.com/lang5230/p/5370424.html

https://refactoringguru.cn/design-patterns/state