设计模式19-状态模式

news2024/12/30 2:05:32

设计模式19-状态模式(State Pattern)

  • 写在前面
    • 状态变化模式
  • 动机
  • 定义与结构
    • 定义
    • 结构
  • C++代码推导
  • 优缺点
  • 应用
  • 总结

写在前面

状态变化模式

  • 在组建构建过程中,某些对象的状态经常面临着变化。如何对这些变化进行有效的管理呢?同时又wage高层模块的稳定。状态变化模式为这一问题提供了一种解决方案。
  • 典型模式
    State
    Memento

动机

  • 在软件构建过程中,某些对象的状态如果改变行为也会随之而发生改变。比如文档处于只读状态,其支持的行为和读写的状态支持的行为就可能完全不同。
  • 如何在运行运行根据对象的状态来透明的更改对象的行为呢?而不会为对象操作和状态转化之间引入紧耦合?
  • 状态模式的动机是通过将状态相关的行为封装到独立的状态对象中,使得当对象的内部状态发生改变时,其行为也会随之改变。状态模式主要用于解决对象在多种状态下具有不同行为的问题,使得状态切换变得更加透明和可维护。

定义与结构

定义

状态模式允许对象在内部状态改变时改变其行为,对象看起来好像修改了它的类。

结构

在这里插入图片描述
这张图展示了一个典型的软件设计模式——状态模式(State Pattern)的架构概念。状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。在这个模式中,定义了一个状态接口(尽管在图中并未直接标出接口名称),它声明了一个或多个处理函数(Handle()),这些函数用于处理在特定状态下的请求。

图中主要包含以下几个关键组件:

  1. 上下文(Context):上下文类负责维护当前状态对象,并定义了一个或多个方法来改变当前状态以及触发状态处理函数。在图中,上下文通过接收一个请求(Request())来触发状态的改变,这个请求通过一个箭头指向了状态(State),表示请求是触发状态变化的原因。

  2. 状态(State):这是一个抽象类或接口,定义了所有可能的状态以及一个或多个处理函数(Handle())。这些处理函数用于执行与状态相关的操作。在图中,状态接口通过虚线表示,暗示它可能是抽象的,并未直接给出实现细节。

  3. 处理函数(Handle()):这是状态接口中定义的方法,用于在特定状态下处理请求。当上下文中的状态改变时,会调用当前状态对象的处理函数来响应请求。

  4. 具体状态(ConcreteStateA, ConcreteStateB):这些是实现了状态接口的具体类,每个类都实现了处理函数的具体逻辑。在图中,有两个具体状态类ConcreteStateA和ConcreteStateB,它们各自有自己的处理函数实现,但具体实现细节未在图中展示。

  5. 状态转换:图中通过箭头从状态指向处理函数(state->Handle())来表示当状态被激活时,相应的处理函数将被调用。这种转换是由上下文中的请求触发的,上下文负责维护当前状态,并根据请求改变状态。

总的来说,这张图通过图形化的方式展示了状态模式的核心概念,即如何根据不同的状态来改变对象的行为。通过定义状态接口和具体状态类,可以在不修改上下文类代码的情况下增加新的状态或修改现有状态的行为,从而提高了系统的可扩展性和可维护性。

C++代码推导

以下是一个使用状态模式的C++代码示例,模拟一个简单的文档工作流,包含草稿、审核和发布三个状态。

状态接口:

#include <iostream>
#include <string>

// 前向声明
class Document;

class State {
public:
    virtual void handleRequest(Document* document) = 0;
    virtual ~State() = default;
};

具体状态类:

class Draft : public State {
public:
    void handleRequest(Document* document) override;
};

class Moderation : public State {
public:
    void handleRequest(Document* document) override;
};

class Published : public State {
public:
    void handleRequest(Document* document) override;
};

文档类(上下文):

class Document {
private:
    State* state;

public:
    Document(State* state) : state(state) {}

    void setState(State* state) {
        this->state = state;
    }

    void request() {
        state->handleRequest(this);
    }

    void displayState(const std::string& stateName) {
        std::cout << "Document is now in " << stateName << " state." << std::endl;
    }
};

具体状态类实现:

void Draft::handleRequest(Document* document) {
    std::cout << "Document is in draft state. Moving to moderation." << std::endl;
    document->setState(new Moderation());
    document->displayState("Moderation");
}

void Moderation::handleRequest(Document* document) {
    std::cout << "Document is in moderation state. Moving to published." << std::endl;
    document->setState(new Published());
    document->displayState("Published");
}

void Published::handleRequest(Document* document) {
    std::cout << "Document is already published. No further action." << std::endl;
}

客户端代码:

int main() {
    Document* document = new Document(new Draft());

    document->request(); // From Draft to Moderation
    document->request(); // From Moderation to Published
    document->request(); // Already Published

    delete document;
    return 0;
}

优缺点

优点:

  1. 简化状态转换:通过将状态转换的逻辑封装在独立的状态类中,使状态转换变得更加明确和简洁。
  2. 遵循开闭原则:添加新状态时,不需要修改上下文类和其他状态类,只需添加新的状态类即可。
  3. 减少条件判断:状态转换逻辑不再依赖于复杂的条件判断,使代码更加清晰和易于维护。

缺点:

  1. 增加类的数量:每个状态都需要一个具体状态类,可能会导致类的数量显著增加。
  2. 状态切换开销:频繁的状态切换可能带来一定的性能开销。

应用

状态模式在以下场景中应用较多:

  1. 对象的行为依赖于其状态:对象在不同状态下有不同的行为,并且对象的状态经常发生变化。
  2. 状态转换逻辑复杂:状态之间的转换逻辑复杂且易变,需要独立处理。
  3. 避免条件语句:需要避免在代码中出现大量的条件语句来处理状态转换逻辑。

总结

  • 状态模式通过将状态相关的行为封装在独立的状态类中,使得对象在不同状态下具有不同的行为,简化了状态转换的逻辑,并提高了系统的可维护性和可扩展性。在适当的场景下使用状态模式,可以显著改善代码的可读性和灵活性。
  • 动态模式将所有与一个特定状态相关的行为放入一个状态的子类对象中。在对象状态切换时切换相应的对象。同时维持状态的接口,这样实现了具体操作与状态转换之间的解耦。
  • 为不同的状态引入不同的对象,使得状态转换变得更加明确。而且可以保证不会出现状态不一致的情况。因为转换是原子性的–你要么彻底转换过来,要么不转换。
  • 如果状态对象没有实例变量,那么各个上下文可以共享同一个状态对象,从而节省对象开销。

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

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

相关文章

特征向量可视化方法介绍

在最近的研究中&#xff0c;实验需要结合可视化进行解释分析&#xff0c;于是大致上了解了下目前一些特征可视化的工具&#xff0c;主要分为四种类型&#xff1a;热力图、散点图、线性图和雷达图&#xff0c;并将相应的基础绘制方法做一个简单的总结。 1 热力图&#xff08;Hea…

向量检索的3种方式

本文介绍向量检索服务如何通过控制台、SDK、API三种不同的方式检索向量。 控制台方式 登录向量检索服务控制台。 在左侧导航栏单击Cluster列表&#xff0c;选中需要检索向量的Collection&#xff0c;单击Collection详情。 在左侧二级导航栏&#xff0c;单击相似向量搜索&…

Leetcode - 136双周赛

目录 一&#xff0c;3238. 求出胜利玩家的数目 二&#xff0c;3239. 最少翻转次数使二进制矩阵回文 I 三&#xff0c;3240. 最少翻转次数使二进制矩阵回文 II 四&#xff0c;3241. 标记所有节点需要的时间 一&#xff0c;3238. 求出胜利玩家的数目 本题直接暴力求解&#x…

springboot招聘管理系统-计算机毕业设计源码26241

摘 要 随着企业的发展和竞争的加剧&#xff0c;人才招聘成为企业人力资源管理中的重要环节。为了提高招聘效率、降低招聘成本&#xff0c;同时提升招聘过程的透明度和公平性&#xff0c;设计并实现一款基于 SpringBoot 的招聘管理系统具有重要的现实意义。 本系统旨在提供一个全…

【MySQL】MySQL常见命令大全

目录 前言一、DQL二 、DML(数据操作语言)部分2.1 插入数据&#xff1a;2.2 更新数据:2.3 删除数据&#xff1a;2.4 创建 create 三、修改 alter四、删除 drop五、表的复制六、常见数据类型 前言 大家好&#xff0c;不知道前面的20题大家写的怎么样&#xff0c;前面分享的20题是…

数据库技术如何增强 AI 大模型?来直播间同拓数派开启探索之旅!

如今&#xff0c;大模型应用正以前所未有的速度改变着各个行业。从自然语言处理、计算机视觉到多模态任务的解决方案&#xff0c;AI 技术已经成为推动业务创新的核心力量。然而&#xff0c;大模型的训练和推理需要处理大量高维度的向量数据&#xff0c;传统数据库在面对这些需求…

3.串口(UART)

串口理论部分可看51部分&#xff1a;链接 数据帧 帧头(2字节&#xff0c;例如AA、BB) 数据长度&#xff08;2字节&#xff09; 数据 CRC16校验&#xff08;2字节&#xff09; 帧尾&#xff08;2字节&#xff09; 代码编写 串口一发送命令控制LED灯(PB5、PE5) LED灯、串口、…

python:基于YOLO框架和遥感图像的目标检测

作者&#xff1a;CSDN _养乐多_ 本文将介绍如何通过YOLO框架和遥感图像进行目标检测的代码。 文章目录 一、数据集下载与格式转换1.1 NWPU VHR-10&#xff08;73.1 MB&#xff09;1.2 DIOR&#xff08;7.06 GB&#xff09;1.3 配置data.yaml 二、训练三、训练结果 一、数据集…

揭秘 NKAbuse:一种滥用 NKN 协议的新型多平台威胁

写在前面的话 在卡巴斯基全球紧急响应团队&#xff08;GERT&#xff09;和GReAT处理的一次网络安全事件应急响应过程中&#xff0c;研究人员发现了一个名为“KNAbuse”的新型多平台网络威胁。这款恶意软件利用了NKN技术在对等节点之间进行数据交换&#xff0c;功能上相当于一种…

NC 合并k个已排序的链表

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 合并 k 个升序…

Ubuntu系统安装docker和docker-compose并解决拉取镜像超时失败问题

安装docker 1、添加Docker官方的GPG密钥: curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - 2、添加docker的软件源 sudo add-apt-repository "deb [archamd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release …

嵌入式软件--C语言高级 DAY 8 函数

函数是C语言尤为重要的知识点&#xff0c;再嵌入式的学习过程中&#xff0c;对51和32的单片机的学习是重中之重。 一、函数的基本概念 1.介绍 函数是一种可重复使用的代码块&#xff0c;用于执行特定的任务或操作。 函数允许我们将代码逻辑组织成独立的单元&#xff0c;从而…

Python酷库之旅-第三方库Pandas(069)

目录 一、用法精讲 276、pandas.Series.dt.is_quarter_start属性 276-1、语法 276-2、参数 276-3、功能 276-4、返回值 276-5、说明 276-6、用法 276-6-1、数据准备 276-6-2、代码示例 276-6-3、结果输出 277、pandas.Series.dt.is_quarter_end属性 277-1、语法 …

知乎ip地址怎么改到别的城市去

知乎全面上线显示用户IP属地功能&#xff0c;这意味着用户可以在知乎上看到其他用户发布内容时的IP属地信息&#xff0c;这有助于增加信息的透明度和减少误解&#xff0c;但同时也容易暴露其隐私。有时出于保护隐私、避免地域限制或参与特定话题讨论的需求&#xff0c;我们可能…

【实战】文件加密器进行逆向

前言 实战可以大大提高自己&#xff0c;学习技术的目的就是能够在实战中运用。 本次实战与实际息息相关&#xff0c;该软件具有加密某文件的功能。 界面还挺好看的&#xff0c;功能很简单&#xff0c;输入文件和PIN(4位&#xff09;进加解密。 这是被加密的文件 需要将其进行…

经纬恒润荣获小米汽车优秀质量奖!

小米SU7上市已超百天&#xff0c;在品质经过客户严选的同时&#xff0c;产量与交付量屡创新高&#xff0c;6-7月连续两个月交付量均超过10000台。为奖励对小米汽车质量和交付做出卓越贡献的合作伙伴团队及个人&#xff0c;小米向质量表现突出的供应商授予了优秀质量奖。经纬恒润…

第22课 Scratch入门篇:猫咪跑步(超长背景实现方法)

猫咪跑步(超长背景实现方法) 故事背景&#xff1a; 在广阔的草坪上有一只小猫&#xff0c;按下键盘的左右键&#xff0c;小猫不停的奔跑。。。 程序原理&#xff1a; 这个小猫的奔跑&#xff0c;实际是背景的移动&#xff0c;上节课我们通过多个图片直接的切换&#xff0c;今天…

深入理解 RDMA 的软硬件交互机制

作者&#xff1a;羽京 一、前言 随着数据中心的飞速发展&#xff0c;高性能网络不断挑战着带宽与时延的极限&#xff0c;网卡带宽从过去的 10 Gb/s 、25 Gb/s 到如今的 100 Gb/s、200 Gb/s 再到下一代的 400Gb/s 网卡&#xff0c;其发展速度已经远大于 CPU 发展的速度。 为了…

谷歌25亿美金收购Character AI的幕后故事

在科技领域中&#xff0c;并购交易无疑是推动技术发展的重要手段之一。最近&#xff0c;谷歌以25亿美金的对价收购了Character AI&#xff0c;这一交易的方式和细节引起了广泛关注。本文将详细解析谷歌这一奇葩交易方式&#xff0c;探讨其背后的动机和影响。 一、交易背景 1.…

计算机毕业设计Python民宿可视化分析 民宿推荐系统 随机森林预测算法 民宿爬虫 酒店爬虫 大数据毕业设计 Django Vue.js 机器学习 深度学习

《Python民宿可视化与预测系统》开题报告 一、选题背景及研究意义 1.1 选题背景 民宿作为一种新型的住宿方式&#xff0c;近年来在全球范围内迅速崛起&#xff0c;尤其在旅游行业发达的国家和地区更是受到广大游客的青睐。民宿不仅提供了更加个性化和接地气的住宿体验&#…