设计模式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)中,状态模式是一个常见的选择,用于建模具有不同状态和事件驱动转换的系统。

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

相关推荐
workflower2 小时前
例二:某汽车制造企业深度融合AI智能体,构建园区网络的智能运维体系
人工智能·机器学习·设计模式·机器人·云计算·汽车·制造
ly76893 小时前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
AI人工智能+电脑小能手5 小时前
大白话说Java设计模式-14-适配器模式(业务实战篇)
java·设计模式·适配器模式·系统兼容·多渠道对接
略略略咯咯14 小时前
(总结)设计模式
设计模式
Cosolar1 天前
DeepSeek Harness 理解 Harness 的设计哲学 - 可组合的插件运行时
人工智能·设计模式·架构
Nebula_g1 天前
JavaSE基础语法:特殊类(特殊情景下的设计模式)
java·开发语言·设计模式
罗小爬EX1 天前
AI Chat 多类型流式事件处理方案(以AgentScope Java 2为例)
java·人工智能·状态模式
George_Ye2 天前
同一本书,一人一份:我如何设计 AI 个性化扫书报告
设计模式
xier_ran2 天前
【infra之路】AI 编译器(二):后端优化
人工智能·状态模式·infra
breeze jiang2 天前
React Todos 前端独立开发全解:用 vite-plugin-mock + axios 封装,再也不等后端接口
前端·react.js·状态模式