设计模式之 状态模式

状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时,改变其行为。这种模式将状态的转换和行为的变化解耦,将不同状态的行为封装到独立的状态类中,而通过上下文(Context)来管理当前状态。每个状态类都负责处理与自己相关的行为,并且能够根据当前的状态转移到下一个状态。

状态模式的主要优点是可以避免在单一类中出现复杂的条件判断语句,增强系统的可扩展性和维护性。

一、状态模式的定义

状态模式允许一个对象在其内部状态改变时,改变其行为。也就是说,状态模式的核心思想是,状态的改变不仅仅是数据的变化,还会影响到行为的变化。每个状态类都有自己的行为实现,而当对象的状态发生变化时,它会切换到一个新的状态对象,这个新的状态对象将根据当前的状态执行相应的行为。

二、状态模式的组成部分

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

  1. Context(上下文)

    上下文类负责维护当前状态并向外界提供一个接口。它还负责在状态变化时更新当前状态对象。上下文通过一个指向状态接口的引用来调用当前状态的行为。
  2. State(状态接口)

    定义一个状态接口,表示对象在不同状态下的行为。每个具体状态类都实现这个接口,并根据当前状态执行具体的操作。
  3. ConcreteState(具体状态类)

    具体的状态类,它实现了状态接口,封装了与该状态相关的行为。每个状态类的实现将描述在该状态下的具体行为和可能的状态转换。

三、状态模式的工作原理

状态模式的工作原理是将对象的所有可能状态封装在状态类中。当对象的状态发生变化时,通过上下文切换到新的状态类,并由新的状态类处理相应的行为。每个状态类内有自己处理请求的逻辑,状态类之间是独立的,并且状态的变化是由上下文自动控制的。

这种模式使得客户端不需要知道具体的状态类,只需要知道当前状态是什么,调用上下文的 request() 方法即可。

四、状态模式的代码示例

假设我们有一个简单的订单处理系统,其中订单的状态有多个,如 待支付已支付已发货 等,每个状态下的订单处理行为不同。

  • 定义状态接口
    public interface State {public void handleOrder(Context context);
    }
  • 创建具体状态类
    public class PendingPaymentState implements State{@Overridepublic void handleOrder(Context context) {System.out.println("订单已支付");context.setState(new PaidState());}
    }
    public class PaidState implements State{@Overridepublic void handleOrder(Context context) {System.out.println("订单已发货");context.setState(new ShippedState());}
    }
    
    public class CompletedState implements State{@Overridepublic void handleOrder(Context context) {System.out.println("订单已完成");}
    }
  • 定义上下文类
    public class Context {private State state;public Context(State state) {this.state = state;}public void setState(State state) {this.state = state;}public void handle(){state.handleOrder(this);}
    }
  • 客户端代码
    public class Client {public static void main(String[] args) {Context context = new Context(new PendingPaymentState());context.handle();context.handle();context.handle();}
    }
  • 运行结果

五、状态模式的优缺点

优点:
  1. 消除复杂的条件判断:状态模式将状态行为与状态的转换分离,避免了在单一类中使用大量 ifswitch 语句。每个状态类只处理其对应状态下的行为,状态之间的切换逻辑也被隔离到不同的类中。

  2. 灵活性和扩展性:当需要增加新的状态时,只需要添加一个新的状态类,而不需要修改现有的代码。这符合开放封闭原则(对扩展开放,对修改关闭)。

  3. 代码更加清晰和易于维护:状态模式将不同的状态行为抽象为独立的类,这使得代码更加模块化,易于理解和维护。

  4. 容易实现状态切换:每个状态类都有自己的行为,当上下文需要切换状态时,只需更新上下文的状态属性即可。状态切换过程封装在状态类中,避免了外部操作的干扰。

缺点:
  1. 类的数量增加:每个状态都会对应一个具体的类,因此如果状态很多,会导致类的数量增加,可能使得系统结构变得复杂。

  2. 状态间切换的耦合性:虽然状态类的行为是独立的,但状态切换本身是通过上下文进行的,可能会导致上下文与状态之间的耦合性较强。

  3. 状态间的过度共享:在某些情况下,不同的状态之间可能有相似的行为或状态转换逻辑,可能导致一些冗余的代码。虽然可以通过抽象层次来减少重复,但也可能增加理解和维护的难度。

六、状态模式的应用场景

  1. 有多个状态的对象:状态模式非常适用于对象有多个不同的状态,并且不同状态下的行为各不相同的场景。比如在一个自动售货机的状态变化过程中,机器根据支付情况、货物是否有库存等条件改变行为。

  2. 工作流管理:在复杂的工作流系统中,每个任务的状态往往决定了任务的处理方式。使用状态模式可以使得每个任务的状态和行为更加清晰独立。

  3. 游戏开发:在游戏中,角色或场景的状态(例如“待机”、“行走”、“攻击”)常常影响到角色的行为。使用状态模式能够简化这些状态的管理。

  4. 事务管理系统:例如订单的不同阶段(如待支付、已支付、已发货等)可能会有不同的处理方法,状态模式能够很好的将不同阶段的处理逻辑分离开来。

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

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

相关文章

JavaScript DOM使用

DOM Document Object Model 简单而言,就是JavaScript将HTML文档的各个组成部分封装为对象。 封装的对象分别为: Document:整个HTML的文档对象 Element:元素对象(也就是HTML中的标签) Attribute:…

uni-app 界面TabBar中间大图标设置的两种方法

一、前言 最近写基于uni-app 写app项目的时候,底部导航栏 中间有一个固定的大图标,并且没有激活状态。这里记录下实现方案。效果如下(党组织这个图标): 方法一:midButton的使用 官方文档:ta…

IText创建加盖公章的pdf文件并生成压缩文件

第一、前言 此前已在文章:Java使用IText根据pdf模板创建pdf文件介绍了Itex的基本使用技巧,本篇以一个案例为基础,主要介绍IText根据pdf模板填充生成pdf文件,并生成压缩文件。 第二、案例 以下面pdf模板为例,生成一个p…

使用 npm 安装 Electron 作为开发依赖

好的,下面是一个使用 npm pack 和 npm install 命令来打包和安装离线版本的 npm 包的具体示例。我们将以 electron 为例,演示如何在有网络连接的机器上打包 electron,然后在没有网络连接的机器上安装它。 步骤 1: 在有网络连接的机器上打包 …

合法三元数量计算

问题描述 小C、小U 和小R 三个好朋友喜欢做一些数字谜题。这次他们遇到一个问题&#xff0c;给定一个长度为n的数组a&#xff0c;他们想要找出符合特定条件的三元组 (i, j, k)。具体来说&#xff0c;三元组要满足 0 < i < j < k < n&#xff0c;并且 max(a[i], a[…

【AI系统】GPU 架构回顾(从2018年-2024年)

Turing 架构 2018 年 Turing 图灵架构发布&#xff0c;采用 TSMC 12 nm 工艺&#xff0c;总共 18.6 亿个晶体管。在 PC 游戏、专业图形应用程序和深度学习推理方面&#xff0c;效率和性能都取得了重大进步。相比上一代 Volta 架构主要更新了 Tensor Core&#xff08;专门为执行…

【高阶数据结构】图论

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是图&#xff0c;并能掌握深度优先遍历和广度优先遍历。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持…

日期(练习)

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title> </head> <body></body> <script>// 定义一个函数&#xff0c;实现格式化日期对象&#xff0c;返回yyyy-MM-dd…

【IDEA】解决总是自动导入全部类(.*)问题

文章目录 问题描述解决方法 我是一名立志把细节说清楚的博主&#xff0c;欢迎【关注】&#x1f389; ~ 原创不易&#xff0c; 如果有帮助 &#xff0c;记得【点赞】【收藏】 哦~ ❥(^_-)~ 如有错误、疑惑&#xff0c;欢迎【评论】指正探讨&#xff0c;我会尽可能第一时间回复…

企业使用知识管理工具与技术的好处(举例说明)

我们都知道“知识就是力量”这句老话&#xff0c;无论是在工作还是个人生活中&#xff0c;我们每一天都越来越认识到这句话的真谛。近年来&#xff0c;不可否认的是&#xff0c;全球范围内我们都在某种程度上缺乏对于许多企业和大型公司至关重要的高端技术技能。 当然&#xf…

机器学习系列-决策树

文章目录 1. 决策树原理决策树的构建流程 2. 案例步骤 1&#xff1a;计算当前节点的熵步骤 2&#xff1a;对每个特征计算分裂后的熵(1) 按“天气”分裂数据集(2) 计算分裂后的加权熵 步骤 3&#xff1a;计算分裂依据信息增益信息增益率GINI系数&#xff08;二叉树&#xff09; …

Android 网络通信(三)OkHttp实现登入

学习笔记 目录 一. 先写XML布局 二、创建 LoginResponse 类 :封装响应数据 目的和作用: 三、创建 MyOkHttp 类 :发送异步请求 代码分析 可能改进的地方 总结 四、LoginActivity 类中实现登录功能 详细分析与注释: 总结: 改进建议: 零、响应数据样例 通过 P…

移动端相关 BFC CSS原子化 ✅

移动端相关 设备宽度&视口 设备宽度是指设备屏幕的实际物理宽度&#xff0c;通常以像素&#xff08;px&#xff09;表示。它是固定的&#xff0c;取决于设备的硬件。不同设备&#xff08;如手机、平板、桌面等&#xff09;有不同的设备宽度。 常被提及的视口可被分为3种…

resnet50,clip,Faiss+Flask简易图文搜索服务

一、实现 文件夹目录结构&#xff1a; templates -----upload.html faiss_app.py 前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widt…

爬虫重定向问题解决

一&#xff0c;问题 做爬虫时会遇到强制重定向的链接&#xff0c;此时可以手动获取重定向后的链接 如下图情况 第二个链接是目标要抓取的&#xff0c;但它是第一个链接重定向过去的&#xff0c;第一个链接接口状态也是302 二&#xff0c;解决方法 请求第一个链接&#xff0c…

一个小的可编辑表格问题引起的思考

11.21工作中遇到的问题 预期&#xff1a;当每行获取红包金额的时候若出现错误&#xff0c;右侧当行会出现提示 结果&#xff1a;获取红包金额出现错误&#xff0c;右侧对应行并没有出现错误提示 我发现&#xff0c;当我们设置readonly的时候&#xff0c;其实render函数依旧是…

解决 vxe-table v3.9 + iview 或者 view-design 中使用 Select 后无法选中的问题

官网文档&#xff1a;https://vxetable.cn 在开发 vue 项目中&#xff0c;使用 vxe-table 时&#xff0c;当同时配合 iview 或者 view-design 组件库使用时&#xff0c;发现一个问题&#xff0c;就是在单元格中渲染 Select 时&#xff0c;会导致下拉选项无法被选中&#xff0c…

「Mac玩转仓颉内测版27」基础篇7 - 字符串类型详解

本篇将介绍 Cangjie 中的字符串类型&#xff0c;包括字符串的定义、字面量形式、插值表达、常用操作及应用场景&#xff0c;帮助开发者熟练掌握字符串的使用。 关键词 字符串类型定义字符串字面量插值字符串字符串拼接常用操作 一、字符串类型概述 在 Cangjie 中&#xff0c;…

一种简单高效的RTSP流在线检测方法,不需要再过渡拉流就可以获取设备状态以及对应音视频通道与编码格式

平台如何检测一路RTSP流是否在线&#xff1f; 在之前的流媒体平台方案中&#xff0c;我们都是通过定时RTSP拉流的方式&#xff0c;走一个完整的RTSP流程&#xff1a;包括OPTIONS、DESCRIBE、SETUP、PLAY、RTP收流&#xff0c;这种方式去取流&#xff0c;然后取到流之后进行流解…

Excel中超链接打开文件时报错 “打开此文件的应用程序没有注册“ 的一个解决办法

需要在Excel中快速打开.bas后缀的文件&#xff0c;所以添加了文件超链接&#xff0c;但是在打开文件的时候报错 “打开此文件的应用程序没有注册” 找到文件直接双击是可以正常打开的&#xff0c;说明是哪里有问题&#xff0c;导致Excel不能找到可以打开文件的程序&#xff0c…