C++设计模式——State状态模式

news2024/9/19 15:16:08

一,状态模式的定义

状态模式是一种行为型设计模式,状态模式允许对象在内部状态发生切换时改变它自身的行为。

状态模式的主要目的是将复杂的状态切换逻辑抽象化为一组离散的状态类,使代码结构更加清晰和易于维护。

状态模式将对象的行为封装到不同的状态类中,从而在应用程序的状态发生改变时,会自动切换到对应的状态类。状态模式使得状态的切换被表现为类对象的切换。

状态模式在现实生活中的抽象实例:

交通信号灯:交通信号灯有红灯、绿灯等多种状态。每个状态都定义了不同的行驶规则。

购物流程:用户在购物流程中有多种状态,例如浏览商品、添加购物车、填写收货地址等。

游戏角色:游戏角色可以处于不同的状态,例如行走、攻击等,玩家可以让角色在不同状态间切换。

订单状态:每个订单包含待支付、已支付、已发货、已完成等多个状态。

二,状态模式的结构

状态模式主要包含以下组件:

1.状态上下文(Context):

状态上下文是一个持有状态对象的类,它持有一个状态对象的引用,对外提供了切换状态的统一接口。

2.抽象状态(State):

它定义了在特定状态下对象的行为,声明了对象在某状态下的操作。

3.具体状态(Concrete State):

包含对抽象状态的具体实现。每个具体状态类代表着一种具体状态,并包含了该状态对应的具体操作。

组件之间的工作步骤如下:

1.初始化状态对象,利用状态对象来初始化状态上下文。

2.状态上下文设置当前状态。

3.状态上下文调用当前状态对应的处理逻辑。

4.状态上下文开始切换状态,并引用另一个状态对象。

对应UML类图:

三,状态模式代码样例

#include <iostream>

class State {
public:
    virtual ~State() {}
    virtual void handle() = 0;
};

class ConcreteStateA: public State {
public:
    void handle() override {
        std::cout << "Handling state A" << std::endl;
    }
};

class ConcreteStateB: public State {
public:
    void handle() override {
        std::cout << "Handling state B" << std::endl;
    }
};

class Context {
private:
    State* state;
public:
    Context(State* state) : state(state) {}
    ~Context() {
        delete state;
    }
    void setState(State* state) {
        delete this->state;
        this->state = state;
    }
    void request() {
        state->handle();
    }
};

int main() {
    State* stateA = new ConcreteStateA();
    State* stateB = new ConcreteStateB();

    Context context(stateA);
    context.request();

    context.setState(stateB);
    context.request();

    return 0;
}

运行结果:

Handling state A
Handling state B

四,状态模式的应用场景

网络管理:网络编程中经常涉及多种网络状态切换,比如发送请求、断开连接等。

分布式系统:分布式系统的节点可能有多种工作状态,比如就绪、运行、故障恢复等。

游戏开发:游戏角色的行为可能会随着生命值、等级、装备的不同而变化。

图形界面开发:在GUI应用中,组件有多种状态,比如按钮有"正常"、"按下"等状态。

五,状态模式的优缺点

状态模式的优点:

修改灵活,当系统需求变化时,可以方便地添加、删除或修改状态,无需修改大量代码。

扩展性强,方便添加新的状态。

代码的结构很清晰,每个状态类专门负责一种特定的行为。

对外隐藏细节,外部只需要关心当前的状态,不需要知道状态转换的细节。

状态模式的缺点:

如果状态很多,会导致类的数量增加。

有些状态处理场景会导致频繁创建和销毁状态对象,带来额外性能开销。

用类对象来表示状态,容易引起过度封装,导致代码结构复杂。

六,代码实战

Demo1:基于状态模式模拟的交通信号灯

#include <iostream>
#include <thread>

class State {
public:
    virtual void handleState() = 0;
};

class GreenState: public State {
public:
    void handleState() override {
        std::cout << "Traffic Light: Green!" << std::endl;
    }
};

class RedState: public State {
public:
    void handleState() override {
        std::cout << "Traffic Light: Red!" << std::endl;
    }
};

class YellowState: public State {
public:
    void handleState() override {
        std::cout << "Traffic Light: Yellow!" << std::endl;
    }
};

class TrafficLight {
private:
    State* currentState;
public:
    TrafficLight(State* initialState){
        currentState = initialState;
    }
    void changeState(State* newState) {
        currentState = newState;
    }
    void operate() {
        currentState->handleState();
    }
};

int main() {
    GreenState greenState;
    RedState redState;
    YellowState yellowState;

    TrafficLight trafficLight(&greenState);
    trafficLight.operate();

    trafficLight.changeState(&yellowState);
    trafficLight.operate();
    trafficLight.changeState(&redState);
    trafficLight.operate();
    
    return 0;
}

运行结果:

Traffic Light: Green!
Traffic Light: Yellow!
Traffic Light: Red!

Demo2:基于状态模式模拟的网络管理

#include <iostream>
class State;

class TCPConnection {
public:
    TCPConnection();
    void open();
    void close();
    void setState(State* newState);
private:
    State* currentState;
};

class State {
public:
    virtual void open(TCPConnection* connection) = 0;
    virtual void close(TCPConnection* connection) = 0;
};

class ReOpenState: public State{
public:
    void open(TCPConnection* connection) override {
        std::cout << "[State3]Network is already ReOpen" << std::endl;
    }
    void close(TCPConnection* connection) override {
        std::cout << "[State3]Closing Network" << std::endl;
    }
};

class ClosedState: public State{
public:
    void open(TCPConnection* connection) override {
        std::cout << "[State2]Opening Network" << std::endl;
        connection->setState(new ReOpenState());
    }
    void close(TCPConnection* connection) override {
        std::cout << "[State2]Network is already closed" << std::endl;
    }
};

class OpenState: public State{
public:
    void open(TCPConnection* connection) override {
        std::cout << "[State1]Network is already open" << std::endl;
    }
    void close(TCPConnection* connection) override {
        std::cout << "[State1]Closing Network" << std::endl;
        connection->setState(new ClosedState());
    }
};

TCPConnection::TCPConnection() : currentState(new OpenState()) {}
void TCPConnection::open() {
    currentState->open(this);
}
void TCPConnection::close() {
    currentState->close(this);
}
void TCPConnection::setState(State* newState) {
    currentState = newState;
}

int main() {
    TCPConnection tcpConnection;

    tcpConnection.open();
    tcpConnection.close();

    tcpConnection.open();
    tcpConnection.close();
    return 0;
}

运行结果:

[State1]Network is already open
[State1]Closing Network
[State2]Opening Network
[State3]Closing Network

七,参考阅读

https://www.javaskool.com/state-design-pattern/

https://www.geeksforgeeks.org/state-design-pattern/

https://softwarepatterns.com/cpp/state-software-pattern-cpp-example

https://www.codeproject.com/Articles/1087619/State-Machine-Design-in-Cplusplus-2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2124011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【spring】IDEA 新建一个spring boot 项目

参考新建项目-sprintboot 选择版本、依赖,我选了一堆 maven会重新下载一次么?

Vue(8)——v-model原理

v-model 原理:v-model本质上是一个语法糖。例如应用在输入框上&#xff0c;就是value和input事件的合写。 作用&#xff1a;提供数据的双向绑定。 数据变&#xff0c;视图跟着变 :value视图变&#xff0c;数据跟着变 input <template><div><input v-model&quo…

【智能体】浅谈大模型之AI Agent

随着ChatGPT推出插件和函数调用功能&#xff0c;构建以LLM&#xff08;大语言模型&#xff09;为核心控制器的AI Agent愈发成为一个拥有无限可能的概念。 AI Agent是一种超越简单文本生成的人工智能系统。它使用大型语言模型&#xff08;LLM&#xff09;作为其核心计算引擎&am…

如何将JSON字符串里面的某个字段的json字符串格式转成json对象?

目录标题 背景临时方案最好的方案 背景 下游传过来的数据是一个json字符串&#xff0c;这个json字符串里面有的字段又套着json字符串&#xff01;还有一些字段直接是null传过来的&#xff01;现在要去掉null&#xff0c;且将一些json字符串&#xff01;尽可能的换成json对象&a…

UE4_后期处理_后期处理材质及后期处理体积一

后期处理效果 在渲染之前应用于整个渲染场景的效果。 后期处理效果&#xff08;Post-processing effect&#xff09;使美术师和设计师能够对影响颜色、色调映射、光照的属性和功能进行组合选择&#xff0c;从而定义场景的整体外观。要访问这些功能&#xff0c;可以将一种称为…

[转]什么是工作流,flowable 与 Activiti对比

工作流 什么是工作流工作流是复杂版本的状态机Java工作流开源框架工作流对比 Activiti 设计器Flowable 兼容性Camunda 设计器兼容性&#xff1a;小结&#xff1a;社区活跃度 FlowableActivitiCamunda总结 什么是工作流 工作流&#xff0c;是指“业务​过程的部分或整体在​计算…

面试题:try和finally中都出现了return语句会发生什么情况

答&#xff1a;会导致提前返回&#xff0c;即执行finally中的return语句&#xff0c;try中的return语句不会被执行。 原因&#xff1a;当try中有return语句时&#xff0c;会延迟返回&#xff0c;即先执行完finally的代码&#xff0c;再执行try的return语句&#xff0c;这样做的…

在windows下抓空包(monitor网卡+wareshark+MNM)

当我们的电脑是通过网线联网时&#xff0c;我们可以通过wareshark来抓取通过网口发送和接收到的包&#xff0c;其中包括单播包、多播包以及广播包等等&#xff0c;只要这个包是通过目标网口的。 但是&#xff0c;如果是无线包呢&#xff1f;我们的无线包其实也是通过无线网卡来…

多目标优化及其MATLAB实现

目录 引言 多目标优化的数学模型 非劣解与Pareto前沿 多目标优化求解方法 MATLAB多目标优化工具 多目标规划中的重要概念 表格总结&#xff1a;常见多目标优化方法及其特点 MATLAB在多目标优化中的应用 结论 引言 多目标优化问题在实际应用中非常常见&#xff0c;因为…

ai学习(2)分词、分词算法、加入注意力机制的Seq2Seq结构模型(编码器、解码器、注意力机制)、日期转换实战代码

文章目录 参考书《多模态大模型&#xff1a;算法、应用与微调》1.分词2.分词算法主流的三种分词算法&#xff0c;BPE分词算法&#xff08;GPT-2、BART、Llama模型&#xff09;、WordPiece分词算法&#xff08;BERT模型&#xff09;、SentencePiece分词算法&#xff08;ChatGLM、…

Linux常见指令、ls、pwd、cd、touch、mkdir、rmdir、rm等的介绍

文章目录 前言一、ls二、pwd三、cd四、touch五、 mkdir六、rmdir七、rm总结 前言 Linux常见指令、ls、pwd、cd、touch、mkdir、rmdir、rm等的介绍 一、ls 列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息 -a 列出目录下的所有文件&#xff0c;…

蓝鹏测控更换新滑台供应商,实现数据平稳性显著提升

近日&#xff0c;蓝鹏测控技术有限公司宣布了一项重要的供应链优化举措——成功更换了其核心设备——滑台的供应商。这一变革不仅优化了公司的生产流程&#xff0c;还显著提升了产品的数据平稳性&#xff0c;达到了惊人的5%提升&#xff0c;标志着蓝鹏测控在提升产品质量与性能…

代码随想录算法训练营第五十三天 | 110.字符串接龙 ,105.有向图的完全可达性 ,106.岛屿的周长

目录 110.字符串接龙 思路 方法一&#xff1a; 广搜 105.有向图的完全可达性 思路 1.确认递归函数&#xff0c;参数 2.确认终止条件 3.处理目前搜索节点出发的路径 方法一&#xff1a;广搜 106.岛屿的周长 思路 解法一&#xff1a; 解法二&#xff1a; 方法一 …

Python | Leetcode Python题解之第398题随机数索引

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, nums: List[int]):self.nums numsdef pick(self, target: int) -> int:ans cnt 0for i, num in enumerate(self.nums):if num target:cnt 1 # 第 cnt 次遇到 targetif randrange(cnt) 0:ans …

15 三数之和

解题思路&#xff1a; \qquad 要找到所有和为0的三元组&#xff0c;使用暴力去解的话时间复杂度为 O ( N 3 ) O(N^3) O(N3)&#xff0c;但是这样会超时。若三数之和为0&#xff0c;那么只要知道其中的两个&#xff0c;就可以知道第三个数的值。进而可以想到用map这样的数据结…

Patch 35586779: WLS PATCH SET UPDATE 10.3.6.0.231017

以上补丁请自行去oracle官网下载&#xff0c;需要技术支持的请联系&#xff1a;https://item.taobao.com/item.htm?spm2013.1.w4023-17257245948.4.19611db9bzrKBx&id608692494369

C语言 | Leetcode C语言题解之第397题整数替换

题目&#xff1a; 题解&#xff1a; //第一种动态规划:超时 // class Solution { // public: // int integerReplacement(int n) { // vector<int>dp(n1,0); // dp[1]0; // for(int i2;i<n;i){ // if(i%20){ // …

Ubuntu查看系统用户信息

0 Preface/Foreword 1 查看方式 1.1 查看系统用户 getent passwd getent: Get entries for Name Service Switch Libraries. 该命令会列出系统上所有用户的详细信息&#xff0c;包括用户名、密码、用户ID&#xff08;UID&#xff09;、组ID&#xff08;GID&#xff09;、用户描…

Python用MarkovRNN马尔可夫递归神经网络建模序列数据t-SNE可视化研究

原文链接&#xff1a;https://tecdat.cn/?p37634 本文聚焦于利用马尔可夫递归神经网络&#xff08;MarkovRNN&#xff09;结合树库展开建模工作。MarkovRNN 通过整合马尔可夫特性与离散随机变量来深入探索递归神经网络中的随机转换机制&#xff0c;旨在高效处理具有复杂潜在信…

轻量级模型解读——GhostNet系列

GhostNet由华为诺亚方舟实验室于2019年11月底提出&#xff0c;投稿于cvpr2020&#xff0c;后面2022年&#xff0c;2024年相继提出更新版本GhostNetv2和GhostNetv3。 它们参数量、复杂度及ImageNet的top1结果对比情况如下&#xff1a; 文章目录 1、GhostNetv11.1 Ghost Module1…