技术成神之路:设计模式(七)状态模式

1.介绍


状态模式(State Pattern)是一种行为设计模式,它允许一个对象在其内部状态改变时改变其行为。这个模式将状态的相关行为封装在独立的状态类中,并将不同状态之间的转换逻辑分离开来。

2.主要作用


状态模式的主要作用是让一个对象在其内部状态改变时,其行为也随之改变,但同时又使得状态的变化对外部来说是透明的。它将状态转移的逻辑封装在状态类中,使得增加新的状态变得简单,同时避免状态间的相互依赖,使得代码更加清晰。

3.解决的问题


状态模式主要解决的问题是对象在不同状态下的行为变化问题,以及状态转换的复杂性管理。

状态模式可以帮助解决以下几类问题:

  1. 消除大量的条件判断语句:
    我们在项目中会经常用到条件判断语句,而有的对象行为会使用到大量的条件语句(如if-else或switch-case)来实现。在某些情况下条件语句少了还好,多了就是灾难,既不美观,又不优雅,唯一好处就是方便使用,但维护起来不方便,如果不使用状态模式,可能需要在每个操作的实现中加入大量的状态判断,这会导致代码复杂、难以维护和扩展。

  2. 状态转换的管理:
    对象的状态不仅仅影响其行为,还涉及到状态之间的转换逻辑。就算你为了方便使用了 if-else或switch-case ,那么处理转换逻辑的代码要写在哪里,状态模式通过将每种状态封装为一个独立的类,使得状态转换的逻辑局部化,每个状态类负责自己的状态判断和转换条件,从而简化了整体的状态管理。

  3. 提高代码的可读性和可维护性:
    这个没什么好说的,设计模式通用✨

4.模式原理


包含角色:

  1. Context(环境类):定义客户感兴趣的接口,并维护一个具体状态子类的实例,这个实例定义当前状态。
  2. State(状态接口/抽象类):定义一个接口或抽象类,封装与Context的一个特定状态相关的行为。
  3. ConcreteState(具体状态类):每一个具体状态类实现了在状态接口中定义的行为,负责状态转换时的逻辑。

了解策略模式的烙铁看到这里是不是很熟悉,包含的角色几乎一模一样,只是把策略两个字改成了状态,那么状态模式是不是就不用继续往下看了?no no no,它们还是有差别滴…

UML类图:
在这里插入图片描述
代码示例:

// State 接口
interface DocumentState {
    void edit(Document doc);
    void save(Document doc);
    void print(Document doc);
}

// ConcreteState 具体状态类
class EditableState implements DocumentState {
    public void edit(Document doc) {
        // 编辑操作
    }
    public void save(Document doc) {
        // 保存操作
    }
    public void print(Document doc) {
        // 打印操作
    }
}

// Context 环境类
class Document {
    private DocumentState currentState;
    
    public Document() {
        this.currentState = new EditableState(); 
    }
    
    public void changeState(DocumentState newState) {
        this.currentState = newState;
    }
    
    public void edit() {
        currentState.edit(this);
    }
    
    public void save() {
        currentState.save(this);
    }
    
    public void print() {
        currentState.print(this);
    }
}

// 使用
Document document = new Document();
document.edit();  
document.save();  
document.print(); 
document.changeState(new ReadOnlyState());
document.edit();  // 无法编辑,状态切换到只读

不知道看到这里,你再回想起策略模式时,是不是还有点迷糊,现在分不清没关系,继续往下看,加深一下印象

状态模式和策略模式区别总结:

  1. 关注点不同:
  • 状态模式关注对象在不同状态下的行为差异,封装了不同状态的行为。
  • 策略模式关注的是算法的不同实现方式,允许算法在不影响客户端的情况下独立变化。
  1. 使用场景不同:
  • 状态模式适用于对象的行为在状态改变时发生改变的情况,状态之间有明显的转换关系。
  • 策略模式适用于客户端需要在多个算法中选择一种时,并且允许在运行时切换算法。
  1. 关系不同:
  • 状态模式中,状态之间存在特定的状态转换关系,通常由Context类来维护和切换状态。
  • 策略模式中,各个策略(算法)之间通常是相互独立的,客户端通过选择不同的策略对象来实现不同的行为。

是不是突然觉得差别还是挺大的嘛,思路一下就清晰了,其实不用理解那么深入,它们的名字就是最大的差异点,通过名字你可以一点一点联想它们的实现方式,这样你就真正理解了设计模式的精髓。

5.优缺点


优点

  • 清晰的状态转换:状态模式将状态和行为封装在独立的类中,使状态转换更加清晰。
  • 提高可维护性和扩展性:通过分离状态和行为,代码更加模块化,便于添加新状态和修改现有状态。
  • 减少条件分支:避免了在上下文类中使用大量的条件分支(if-else 或 switch-case)。

缺点

  • 增加类的数量:每个状态都需要一个类,可能会导致系统中类的数量增加,从而增加维护难度(设计模式通病)。
  • 状态之间的依赖:某些状态可能依赖于其他状态,导致状态类之间的耦合(此条可忽略)。

6.应用场景


状态模式 状态模式 首先你得有不同状态才行,举几个简单场景:

  • 对象行为依赖于其状态:如电灯开关、文档编辑器的状态(如草稿、审核中、已发布等)。
  • 状态转换复杂:状态之间存在复杂的转换逻辑,需要清晰地管理状态和行为。
  • 需要频繁更改状态或扩展新状态:如游戏角色的状态、工作流引擎的状态等。

7.总结


状态模式通过将状态和状态相关的行为封装在独立的类中,使得状态转换逻辑更加清晰和可维护。它提高了代码的扩展性和可维护性,适用于对象行为依赖于状态且状态转换复杂的场景。然而,需要注意的是,状态模式可能会增加系统中类的数量,使得系统的维护变得更加复杂。在使用状态模式时,需要权衡其带来的好处和潜在的复杂性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

16001.WSL2 ubuntu20.04 编译安装 vsomeip

文章目录 1 vsomeip 编译安装1.1 vsomeip的安装1.2 编译提示错误1.3 编译hello_world示例1.4 运行服务器端 1 vsomeip 编译安装 1.1 vsomeip的安装 参考博文 https://blog.csdn.net/peterwanye/article/details/128386539 1.2 编译提示错误 ubuntu1-BJ-EE1000042:~/opt/vso…

科研绘图系列:R语言分组散点图(grouped scatter plot)

介绍 分组连线散点图是一种高效的数据可视化手段,它通过在散点图上添加线条来明确展示数据点的分组情况。这种图形能够显著地突出不同组之间的差异,为读者提供了一种直观且易于理解的方式来识别数据的聚类结构。相较于传统的散点图,分组连线散点图在展示数据分组信息方面更…

linux centos limits.conf 修改错误,无法登陆问题修复 centos7.9

一、问题描述 由于修改/etc/security/limits.conf这个文件中的值不当,重启后会导致其账户无法远程登录,本机登录。 如改成这样《错误示范》: 会出现: 二、解决 现在知道是由于修改limits.conf文件不当造成的,那么就…

MyBatis框架学习笔记(四):动态SQL语句、映射关系和缓存

1 动态 SQL 语句-更复杂的查询业务需求 1.1 动态 SQL-官方文档 (1)文档地址: mybatis – MyBatis 3 | 动态 SQL (2)为什么需要动态 SQL 动态 SQL 是 MyBatis 的强大特性之一 使用 JDBC 或其它类似的框架,根据不同条…

PHP多功能投票微信小程序系统源码

🎉一键决策,尽在掌握!多功能投票小程序,让选择不再纠结🤔 📲【开篇:告别传统,拥抱便捷投票新时代】📲 还在为组织投票活动手忙脚乱?或是面对众多选项犹豫不…

数据库:编程(打开、操作(增、删、改、查)、关闭)

一、需要的头文件 sqlite3.h 二、编译过程 gcc xxx -lsqlite3 三、编程框架 打开数据库 》读写数据库(增,删,改,查) 》关闭数据库 3.1 打开数据库: sqlite3_open int sqlite3_open(char * path,sqlite3 ** db); 功能&…

无人机之机架类型篇

碳纤维机架 具有低密度、高强度和高刚度的特点,非常适合商业或工业级无人机的设计。碳纤维机架在飞行过程中具有良好的减振效果,使飞行更加稳定,但制作工艺复杂,成本较高。 工程塑料机架 以其轻便、耐冲击和易加工等特点受到一…

SpringCloud | 单体商城项目拆分(微服务)

为什么要进行微服务拆分? 在平常的商城项目中,我们一般的项目结构模块都是将各种业务放在同一个项目文件夹,比如像: 用户,购物车,商品,订单,支付等业务都是放在一起,这样…

SpringBoot以及swagger的基本使用

1、SpringBoot是什么? 一种快速开发、启动Spring的框架、脚手架 遵循“约定优于配置”的思想,使得能够快速创建和配置Spring应用 2、SpringBoot的核心特性 自动配置,一些依赖、默认配置都预设好了,减少了配置量起步依赖&#x…

Docker的安装【虚拟机】

Docker的安装【虚拟机】 1、查看是否含有旧版本 yum list installed|grep docker2、安装docker仓库 yum -y install yum-utils3、设置docker仓库 # 清理 yum 的所有缓存 yum clean all # 更新并生成 yum 软件仓库的元数据缓存,确保系统使用的软件信息是最新的 y…

ASP.NET MVC-制作可排序的表格组件-PagedList版

环境: win10 参考: 学习ASP.NET MVC(十一)——分页 - DotNet菜园 - 博客园 https://www.cnblogs.com/chillsrc/p/6554697.html ASP.NET MVCEF框架实现分页_ef 异步分页-CSDN博客 https://blog.csdn.net/qq_40052237/article/details/106599528 本文略去…

嵌入式linux相机 框图

摄像头读取数据显示到LCD流程 重点:摄像头数据(yuyv,mjpeg,rgb)(640,320)与LCD显示数据(RGB)(480,240)不同;需要转换&…

数据结构——考研笔记(三)线性表之单链表

文章目录 2.3 单链表2.3.1 知识总览2.3.2 什么是单链表2.3.3 不带头结点的单链表2.3.4 带头结点的单链表2.3.5 不带头结点 VS 带头结点2.3.6 知识回顾与重要考点2.3.7 单链表的插入和删除2.3.7.1 按位序插入(带头结点)2.3.7.2 按位序插入(不带…

如何使用 GPT?

​通过实例,来展示如何最好地使用 GPT。 生成文字 假设你在写一篇文章,需要在结尾加上这样一句:「California’s population is 53 times that of Alaska.」(加州的人口是阿拉斯加州的 53 倍)。 但现在你不知道这两个…

Git钩子Hook功能

💾 Hook 钩子 目录 🔔 简介🔔 常见类型🔔 如何配置🔔 使用场景🔔 示例 🔔 简介 Git Hooks是Git内置的一种机制,允许在特定事件发生时执行自定义脚本。Git Hook可以在客户端和服务器端…

SpringBoot整合阿里云RocketMQ对接,商业版

1.需要阿里云开通商业版RocketMQ 普通消息新建普通主题,普通组,延迟消息新建延迟消息主题,延迟消息组 2.结构目录 3.引入依赖 <!--阿里云RocketMq整合--><dependency><groupId>com.aliyun.openservices</groupId><artifactId>ons-client</…

[论文笔记]构建基于RAG聊天机器人的要素

引言 今天带来一篇构建RAG的论文笔记&#xff1a;FACTS About Building Retrieval Augmented Generation-based Chatbots。 基于生成式人工智能构建企业聊天机器人迅速成为行业中最受关注的应用之一&#xff0c;旨在提高员工生产力。 然而&#xff0c;构建成功的企业聊天机器…

爬虫-requests和Selenium

1、了解requests的功能 1.1 使用post和get发送请求 HTTP中常见发送网络请求的方式有两种&#xff0c;GET和POST。GET是从指定的资源请求数据&#xff0c;POST是向指定的资源提交要被处理的数据。 GET的用法&#xff1a; import requestsr requests.get("https://www.…

随机过程基础:2.Markov (马尔可夫)过程(2)

纯生过程和纯灭过程 纯生过程&#xff1a;想象一下一个生物种群&#xff0c;比如一群兔子&#xff0c;在没有天敌的理想环境中&#xff0c;食物充足&#xff0c;疾病不存在。在这样的环境下&#xff0c;兔子的种群只会增加&#xff0c;不会减少。纯生过程模型就是用来描述这种情…

Android使用ANativeWindow更新surfaceView内容最简Demo

SurfaceView简介 SurfaceView对比View的区别 安卓的普通VIew,都依赖于当前Activity的Window的surface&#xff0c;这个surface用于承载view树从底到顶绘制出来的所有内容&#xff0c;因此任何一个view需要更新时&#xff0c;都需要把所有view中底到顶进行更新&#xff0c;即使使…