java设计模式学习之【状态模式】
文章目录
- 引言
- 状态模式简介
- 定义与用途
- 实现方式
- 使用场景
- 优势与劣势
- 在Spring框架中的应用
- 状态示例
- 代码地址
引言
设想你正在使用一个在线视频播放器观看电影。随着你的互动,播放器可能处于不同的状态:播放、暂停、缓冲或结束。每个状态下,播放器的行为和可用选项都不同。这种能够根据当前状态调整行为的能力对于创建直观、响应灵敏的应用至关重要。在软件开发中,状态模式正是用来优雅地处理这种依赖状态的行为变化的情况,它帮助设计者清晰地分离和管理对象在不同状态下的行为。
状态模式简介
定义与用途
状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为。对象似乎修改了它的类。该模式封装了基于状态的行为,并且通过将每个状态实现为一个派生类的方式,将状态相关的行为局部化和集中化。
实现方式
实现状态模式通常涉及以下几个关键组件:
- 上下文(Context):持有一个状态对象的引用,并允许外部客户端触发状态变化。
- 状态(State):定义一个接口以封装与上下文的一个特定状态相关的行为。
- 具体状态(Concrete States):实现状态接口的类,提供具体的行为实现。
使用场景
状态模式适用于以下场景:
- 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
- 当一个操作中含有庞大的多分支结构,并且这些分支依赖于对象的状态时。
例如:
- 文档审批流程:文档在创建、审批、发布等不同状态之间转换,每个状态下文档的行为(如编辑、审批、发布)不同。
- 交通信号灯:信号灯根据时间或条件变化其状态(红灯、绿灯、黄灯),每种状态下的行为(比如停车、行驶)也不同。
- 游戏中的角色状态:游戏角色可能有多种状态(正常、加速、减速、无敌等),每种状态下角色的行为和属性有所不同。
优势与劣势
- 优势
- 封装了基于状态的行为,并且将状态相关的行为局部化。
- 通过消除庞大的条件分支语句,使得状态转换显式化。
- 劣势
- 如果状态多且复杂,会导致有很多状态类,增加系统复杂度。
- 应用不当会导致状态和策略模式混淆。
在Spring框架中的应用
在Spring框架中,状态模式可能不会像某些其他模式那样直接被提及,但是其核心概念在某些Spring的功能和管理方式中得到了体现。以下是在Spring框架中体现状态模式概念的几个方面:
1. Spring状态机(Spring State Machine)
Spring状态机(Spring State Machine)是对状态模式概念的直接实现。它提供了一个强大的方式来管理状态转换以及状态下的行为。在复杂逻辑和工作流的情况下,如订单管理、配置管理等,Spring状态机可以帮助开发者以声明性的方式管理状态和事件。2. Spring Web Flow
在Spring Web Flow中,状态模式的概念被用于管理Web应用中的页面流。页面流可以看作是一系列状态和发生在这些状态之间的事件。Spring Web Flow允许开发者定义页面流程的状态(如视图状态、决策状态等),并且基于发生的事件移动到不同的状态,从而提供丰富的用户界面导航。3. Spring Security的认证状态
在Spring Security中,用户的认证状态(如已认证、未认证、认证失败等)可以被看作是用户在安全上下文中的状态。Spring Security使用一系列的过滤器和认证管理器来处理这些状态变化,并执行相应的安全逻辑。4. Session和会话管理
在Spring MVC中,会话(Session)的状态管理也可以被看作是状态模式的一个例子。会话中的数据代表了用户的状态(如用户认证、选择的语言、配置偏好等),这些状态可能会随着用户的交互而改变。
状态示例
步骤 1:创建接口
public interface State {public void doAction(Context context);
}
State 接口定义了一个 doAction 方法,所有的具体状态类将实现这个接口,以提供相应的行为。
步骤 2:创建实现相同接口的具体类
public class StartState implements State {public void doAction(Context context) {System.out.println("播放器处于开始状态");context.setState(this); }public String toString(){return "开始状态";}
}
StartState 是一个具体的状态类,表示开始状态。当播放器处于这个状态时,它将执行相应的操作并更新上下文状态。
public class StopState implements State{@Overridepublic void doAction(Context context) {System.out.println("播放器处于停止状态");context.setState(this);}@Overridepublic String toString(){return "停止状态";}}
StopState 是另一个具体的状态类,表示停止状态。在这个状态下,它将执行停止状态下的操作并更新上下文状态。
步骤 3:创建上下文类
public class Context {private State state;public Context(){state = null;}public void setState(State state){this.state = state; }public State getState(){return state;}
}
Context 类持有一个状态对象的引用,并允许客户端通过 setState 方法改变其状态。它的行为随着状态的改变而改变。
步骤 4:使用上下文来看到状态改变时的行为变化
public class StatePatternDemo {public static void main(String[] args) {Context context = new Context();StartState startState = new StartState();startState.doAction(context);System.out.println("当前状态: " + context.getState().toString());StopState stopState = new StopState();stopState.doAction(context);System.out.println("当前状态: " + context.getState().toString());}
}
在这个演示类中,我们创建了一个上下文对象并改变其状态。首先,我们将上下文设置为开始状态并执行相关操作,然后我们将上下文设置为停止状态并执行相关操作。在每个状态改变后,我们都打印出当前的状态来看到行为的变化。
这个示例演示了状态模式如何使对象的行为随其状态的改变而改变。通过将每个状态的行为封装在单独的类中,我们可以很容易地增加新的状态和行为,同时保持不同状态的行为分离和独立。
代码地址
23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern
相关文章:

java设计模式学习之【状态模式】
文章目录 引言状态模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用状态示例代码地址 引言 设想你正在使用一个在线视频播放器观看电影。随着你的互动,播放器可能处于不同的状态:播放、暂停、缓冲或结束。每个状态下,播放…...

使用aspose.Words更新表格列宽
public static bool UpdateTableStyle(string filePath) { try { Document doc new Document(); //样式 Style style doc.Styles.Add(StyleType.Paragraph, "cellStyle"); style.Font.Name "simsun"; PageSetup pageSet doc.Sections[0].PageSetup; pa…...

pycharm 工具栏不见了
新版pycharm后, 菜单栏和工具栏不见了 目录 我发现的解决方法: 其他旧版的解决方法: 我发现的解决方法: 其他旧版的解决方法: 另外,一些使用pycharm的新手可能会由于不熟悉软件的功能而误操作ÿ…...

图灵日记之java奇妙历险记--类和对象
目录 类的定义和使用类的定义格式 类的实例化类和对象的说明 this引用this引用的特性 对象的构造及初始化就地初始化构造方法 封装包导入包中的类自定义包 static成员static修饰成员变量static修饰成员方法 代码块代码块概念及分类构造代码块静态代码块 匿名对象 类的定义和使用…...

Kotlin 枚举类
使用 enum 修饰符;每个枚举常量都是一个对象,枚举常量以逗号分隔 // 枚举类 enum class Direction {NORTH, SOUTH, WEST, EAST }// 每一个枚举都是枚举类的实例,所以可以这样初始化 enum class Color(val rgb: Int) {RED(0xFF0000),GREEN(0x…...

可运营的Leadshop开源商城小程序源码 +H5公众号+带视频教程
源码简介 Leadshop是一款出色的开源电商系统,具备轻量级、高性能的特点,并提供持续更新和迭代服务。该系统采用前后端分离架构(uniappyii2.0),以实现最佳用户体验为目标。 前端部分采用了uni-app、ES6、Vue、Vuex、V…...

Qt底层机制之对象树总结
Qt对象树是Qt框架中的一个重要概念,它用于管理对象之间的关系和生命周期。除了常规的对象树结构,Qt还提供了一些特殊的用法来扩展对象树的功能和灵活性。 1. 父子关系:Qt对象树通过设置父对象来建立父子关系。父对象负责管理子对象的内存分配和释放。这种关系可以通过`setP…...

QT C++ TCP Socket 请求心知天气
0.0 相关连接代码部分头文件具体实现 相关连接 心知天气官方天气图标 心知天气官网 代码部分 头文件 #include <QtNetwork> #include <QNetworkAccessManager> #include <QDebug> #include <QJsonValue> #include <QJsonArray> #include &l…...

双向链表的实现及头尾插入删除
双链表的增删查改 一.双向链表的初始化二.创建返回链表的头结点三.双向链表销毁四. 双向链表打印五.双向链表尾插六. 双向链表尾删七. 双向链表头插八.双向链表头删九.双向链表的查找十.双向链表在pos的前面进行插入十一. 双向链表删除pos位置的节点 一.双向链表的初始化 Lis…...

C语言—每日选择题—Day62
第一题 1. 在使用标准C库时,下面哪个选项使用只读模式打开文件? A:fopen("foo.txt", "r") B:fopen("foo.txt", "r") C:fopen("foo.txt", "w") D…...

基于 Sentry 的前端监控系统搭建(Linux)
一、前言 随着技术这几年的发展与沉淀,线上数据指标监控也变得尤为重要,研发人员和运营人员需要对线上的产品指标有所感知,同时风险也需要及时暴露,很多公司开始自建监控系统,但对于一些定制化要求不是特别高的团队&a…...

【C++入门到精通】Lock_guard与Unique_lock C++11 [ C++入门 ]
阅读导航 引言一、RAII机制1. 概念2. 原理3. 优点 二、Lock_guard1. 官方文档2. 概念3. 底层类模版4. 使用示例 三、Unique_lock1. 官方文档2. 概念及底层3. 使用示例 四、总结温馨提示 引言 在C11标准中,为了更方便地使用互斥锁(Mutex)来保…...

电路设计(8)——计时器的multism仿真
1.功能设计 这是一个计时电路,在秒脉冲的驱动下,计时器开始累加,6个数码管分别显示计时的 时:分:秒。 仿真图如下所示: 左边的运放构成了振荡电路,可以产生脉冲波。这个脉冲波给计时电路提供基准…...

Jmeter测试实践:文件下载接口
一 Jmeter步骤 1.打开jmeter4.0,新建测试计划,添加线程组。根据实际情况配置线程属性。 2.添加HTTP请求。根据接口文档进行配置。 Basic部分修改如下,Advanced部分保持默认。这里的参数id是文件的id,我进行了参数化,…...

PyQt5实现学生管理系统第三天(下)
目录 一:学生课程导航 二:搜索框 三:查询 四:页面数据展示逻辑 上一节,我们介绍了课程管理的课程查询导航的功能。这一节我们介绍下学生课程的功能实现,因为学生课程只有一个查询列表,内容相对简单,所以我们在这一节也重点讲述下我们页面的展现逻辑。 一:学生课程…...
第4章 | 安徽某高校《统计建模与R软件》期末复习
第4章 参数估计 参数估计是统计建模的关键步骤之一,它涉及根据样本数据推断总体参数的过程。在统计学中,参数通常用于描述总体的特征,如均值、方差等。通过参数估计,我们可以利用样本信息对这些未知参数进行推断,从而…...

localforage本地存储(融合Web Storage,Web SQL Database,ndexedDB三种前端存储)
介绍 localForage 是一个快速而简单的 JavaScript 存储库。通过使用异步存储(IndexedDB 或 WebSQL)和简单的类 localStorage 的 API ,localForage 能改善 Web 应用的离线体验。 在不支持 IndexedDB 或 WebSQL 的浏览器中,localF…...

【JavaWeb学习笔记】17 - ThreadLocal
项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/threadlocal/src/com/yinhai/thread 目录 项目代码 一、什么是ThreadLocal? 二、ThreadLocal快速入门 三、源码解读 一、什么是ThreadLocal? 1. ThreadLocal的作用,可以实现在同一个线…...

【ARMv8M Cortex-M33 系列 1 -- SAU 介绍】
文章目录 Cortex-M33 SAU 介绍SAU 的主要功能包括SAU 寄存器配置示例 Cortex-M33 SAU 介绍 在 ARMv8-M 架构中,SAU(Security Attribution Unit)是安全属性单元,用于配置和管理内存区域的安全属性。SAU 是 ARM TrustZone 技术的一…...

sklearn 逻辑回归Demo
逻辑回归案例 假设表示 基于上述情况,要使分类器的输出在[0,1]之间,可以采用假设表示的方法。 设 h θ ( x ) g ( θ T x ) h_θ (x)g(θ^T x) hθ(x)g(θTx), 其中 g ( z ) 1 ( 1 e − z ) g(z)\frac{1}{(1e^{−z} )} g(z)(1e−z)1…...

什么是众创空间?他有什么特点?
众创空间,是一种为大众创新创业提供专业化服务的创业服务平台,是顺应网络时代创新创业特点和需求,通过市场化机制、专业化服务和资本化途径构建的低成本、便利化、全要素、开放式的新型创业服务平台的统称。众创空间包括创客空间、联合办公空…...

什么是数据分析思维
参考 一文学会如何做电商数据分析(附运营分析指标框架) 电子商务该如何做数据分析?如何数据分析入门(从各项指标表象进入) https://www.processon.com/outline/6589838c3129f1550cc69950 数据分析步骤 什么是数据分析…...

利用Milvus Cloud和LangChain构建机器人:一种引人入胜且通俗易懂的方法
一、引言 机器人已经深入我们的日常生活,从家庭服务到工业生产,再到医疗和运输等领域。然而,这些机器人往往需要复杂的算法和数据处理技术才能有效地执行任务。在这个过程中,人工智能(AI)和机器学习&#…...

数据结构-如何实现一个队列?逐步解析与代码示例(超详细)
文章目录 前言1.队列的基本概念2.链表与数组实现队列的区别2.1数据存储结构2.2性能2.3内存使用 3.为什么选择链表实现队列?4.结构定义函数声明 5.核心操作5.1初始化 (QInit)5.2销毁 (QDestroy)5.3入队 (QPush)5.4出队 (QPop) 6.队列的查询操作6.1队首元素 (QueueFro…...

爬虫工作量由小到大的思维转变---<第二十三章 Scrapy开始很快,越来越慢(医病篇)>
诊断篇https://blog.csdn.net/m0_56758840/article/details/135170994?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170333243316800180644102%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id1703332433168001806441…...

.Net7.0 或更高版本 System.Drawing.Common 上传图片跨平台方案
项目升级.Net7.0以后,System.Drawing.Common开关已经被删除,且System.Drawing.Common仅在 Windows 上支持 ,于是想办法将原来上传图片验证文件名和获取图片扩展名方法替换一下,便开始搜索相关解决方案。 .Net6.0文档:…...

【MySQL】InnoDB和MyISAM区别
文章目录 一、索引不同1 InnoDB聚簇索引,MyISAM非聚簇索引1 InnoDB聚簇索引2 MyISAM非聚簇索引 2 InnoDB必须要有主键,MyISAM允许没有主键3 InnoDB支持外键4 InnoDB不支持全文索引5 索引保存位置不同 二、对事物的支持三、存储结构不同四、存储空间不同五…...

3分钟了解安全数据交换系统有什么用!
企业为了保护核心数据安全,都会采取一些措施,比如做网络隔离划分,分成了不同的安全级别网络,或者安全域,接下来就是需要建设跨网络、跨安全域的安全数据交换系统,将安全保障与数据交换功能有机整合在一起&a…...

记录汇川:MODBUS TCP-梯形图
H5U的MODBUS通信不需要编写程序,通过组态MODBUS通信配置表,实现数据通信。 Modbus-TCP 主站即Modbus-TCP客户端,通过Modbus-TCP配置,可最多支持同时与31个 Modbus-TCP服务器(从站)进行通讯。 …...

electron + sqlite3 解决打包后无法写入数据库
前言 window环境。 electron28.0.0 sqlite35.1.6 使用 electron-builder 打包。 本文旨在解决打包后无法写入数据库的问题。 但如果你是打包后无法访问sqlite,且有报错弹窗,不妨也看看本文。 也许是同一种原因。 错误原因分析 打包后无法创建db文件&…...