设计模式12:状态模式

系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客

参考:设计模式之状态模式 (C++ 实现)_设计模式的状态模式实现-CSDN博客

1.概述

状态模式允许一个对象在其内部状态改变时改变其行为。对象看起来像是改变了其类。使用状态模式可以将状态的相关行为放在各个状态类中,从而实现状态切换的灵活性和可扩展性。

用例子来说明,小明是个大学生(对象),简化其状态为:困,饿,饱;简化行为:吃饭,睡觉,打王者;默认情况下小明的行为和状态之间的关系会有偶然性,所以会存在逻辑上的if-else组合,要考虑地全面,这分支无疑会比较多,并且可以出错。如果从状态模式处理小明状态和行为的逻辑问题,可以把小明的状态抽象为状态类(State ),各种具体的状态定为其的继承类(ConcreteState ),小明具体如何在行为和状态间切换的场景类(Context)。这样会比较清晰,各自的状态类下和其相关的行为会比较清晰;如果想新增状态类,也比较方便。

2.结构与实现

结构:

状态模式主要由以下几个部分构成:

  1. Context (上下文):持有一个具体的状态对象,并在状态之间切换。
  2. State (状态接口):定义一个接口用于在具体状态中实现不同的行为。
  3. ConcreteState (具体状态):实现状态接口的具体类,每个状态都有自己的行为。

实现:

参照概述的中例子,实现如下:

State.h:

cpp 复制代码
#ifndef STATE_H
#define STATE_H

#include <QDebug>

class People;

class State
{
public:
    State() {}
    virtual void sleep(People* xiaoming)=0;
    virtual void eat(People* xiaoming)=0;
    virtual void playWangzhe(People* xiaoming)=0;
};

//疲劳
class tiredState : public State
{
public:
    tiredState(){}
    void sleep(People* people);
    void eat(People* people);
    void playWangzhe(People* people);
};

//饥饿
class hungryState : public State
{
public:
    hungryState(){}
    void sleep(People* people);
    void eat(People* people);
    void playWangzhe(People* people);
};

//饱
class fullState : public State
{
public:
    fullState(){}
    void sleep(People* people);
    void eat(People* people);
    void playWangzhe(People* people);
};

#endif // STATE_H

State.cpp:

cpp 复制代码
#include "State.h"
#include "People.h"

void tiredState::sleep(People *people)
{
    qDebug() << "tired, go to sleeping and hungry.";
    people->setState(new hungryState());
}

void tiredState::eat(People *people)
{
    qDebug() << "tired, no want to eat...";
}

void tiredState::playWangzhe(People *people)
{
    qDebug() << "tired, no want to play...";
}

void hungryState::sleep(People *people)
{
    qDebug() << "hungry, no want to sleep...";
}

void hungryState::eat(People *people)
{
    qDebug() << "hungry, go to eat and full.";
    people->setState(new fullState());
}

void hungryState::playWangzhe(People *people)
{
    qDebug() << "hungry, no want to play...";
}

void fullState::sleep(People *people)
{
    qDebug() << "full, no want to sleep...";
}

void fullState::eat(People *people)
{
    qDebug() << "full, no want to eat...";
}

void fullState::playWangzhe(People *people)
{
    qDebug() << "full, go to play wangzhe and tired.";
    people->setState(new tiredState());
}

People.h:

cpp 复制代码
#ifndef PEOPLE_H
#define PEOPLE_H

#include "State.h"

class People
{
public:
    People() {state = new tiredState();}
    ~People(){delete state;}

    void setState(State* newState){
        delete state;
        state = newState;
    }
    void play();
    void sleep();
    void eat();

private:
    State* state;
};
#endif // PEOPLE_H

People.cpp:

cpp 复制代码
#include "People.h"
void People::play()
{
    state->playWangzhe(this);
}

void People::sleep()
{
    state->sleep(this);
}

void People::eat()
{
    state->eat(this);
}

main.cpp:

cpp 复制代码
#include <QCoreApplication>
#include "People.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    People* xiaoming = new People();
    xiaoming->eat();
    xiaoming->play();
    xiaoming->sleep();
    xiaoming->eat();
    xiaoming->play();
    xiaoming->eat();

    delete xiaoming;
    return 0;
}

运行效果:

bash 复制代码
tired, no want to eat...
tired, no want to play...
tired, go to sleeping and hungry.
hungry, go to eat and full.
full, go to play wangzhe and tired.
tired, no want to eat...

3.应用

状态机,游戏开发、网络协议处理、用户界面

4.优缺点及适用环境

优点:

  1. 简化对象的实现:通过将不同的状态逻辑分离到不同的类中,可以使原本复杂的条件语句变得更加简单明了。
  2. 符合开闭原则:当需要增加新的状态时,只需添加新的状态类而无需修改现有的代码,提高了系统的可扩展性。
  3. 提高内聚性:每个状态的行为被封装在一个单独的类中,增强了模块化和内聚性。
  4. 清晰的状态转换:状态模式使得状态之间的转换更加明确和易于管理。

缺点:

  1. 可能引入过多的类:对于每一个状态都需要创建一个新的类,这可能会导致系统中有过多的小类,增加了复杂度。
  2. 状态爆炸问题:如果状态之间存在多种组合,那么将会产生大量的状态类,维护起来较为困难。
  3. 上下文与状态之间的耦合:状态对象通常依赖于上下文对象,反之亦然,这可能导致较高的耦合度。

应用环境:

  • 当一个对象在它的生命周期中需要根据不同的状态表现出不同的行为时。
  • 当状态转换的逻辑复杂,使用多个条件语句来处理会使得代码难以理解和维护时。
  • 当系统中存在大量相似但又有些许差异的状态或行为时,可以利用状态模式来减少重复代码并提高灵活性。
  • 在有限状态机(FSM)中,状态模式是一个常见的选择,用于建模具有不同状态和事件驱动转换的系统。

综上所述,状态模式适用于那些有明显状态变化并且这些状态变化会导致行为变更的情况,尤其是在你希望保持代码整洁、易于扩展的情况下。

相关推荐
等一场春雨12 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式
等一场春雨15 小时前
Java设计模式 十四 行为型模式 (Behavioral Patterns)
java·开发语言·设计模式
小王子102418 小时前
设计模式Python版 单例模式
python·单例模式·设计模式
_DCG_18 小时前
c++常见设计模式之装饰器模式
c++·设计模式·装饰器模式
快乐非自愿18 小时前
「全网最细 + 实战源码案例」设计模式——单例设计模式
java·单例模式·设计模式
阿绵18 小时前
设计模式-模板方法实现
java·开发语言·设计模式
晚秋贰拾伍18 小时前
设计模式的艺术-职责链模式
运维·设计模式·运维开发·责任链模式·开闭原则·单一职责原则
博一波18 小时前
【设计模式-行为型】状态模式
设计模式·状态模式
w(゚Д゚)w吓洗宝宝了18 小时前
设计模式概述 - 设计模式的重要性
c++·设计模式
Cikiss18 小时前
「全网最细 + 实战源码案例」设计模式——工厂方法模式
java·后端·设计模式·工厂方法模式