【设计模式】行为型-状态模式

在变幻的时光中,状态如诗篇般细腻流转。

文章目录

  • 一、可调节的灯光
  • 二、状态模式
  • 三、状态模式的核心组件
  • 四、运用状态模式
  • 五、状态模式的应用场景
  • 六、小结
  • 推荐阅读

一、可调节的灯光

场景假设:我们有一个电灯,它可以被打开和关闭。用户可以通过一个开关来改变电灯的状态。

/*** 表示可以开关的灯的类。*/
public class Light {private String state; // 灯的当前状态,可能是"ON"或者"OFF"/*** 构造方法,初始化灯的状态为"OFF"。*/public Light() {this.state = "OFF";}/*** 开关灯的状态。* 如果灯当前为"OFF",则将其改为"ON"并打印"灯已打开"。* 如果灯当前为"ON",则将其改为"OFF"并打印"灯已关闭"。*/public void switchState() {if ("OFF".equals(state)) {state = "ON";System.out.println("灯已打开");} else {state = "OFF";System.out.println("灯已关闭");}}
}

上面的代码虽然能够实现需求,因为只有两种状态。但是,如果电灯有更多的状态,比如“调暗”、“调亮”、“闪烁”等,那么 switchState 方法就会变得非常复杂,充满了 if-else 语句。这将使代码难以阅读和维护。

二、状态模式

状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态发生改变时改变其行为,使其看起来像是改变了其类。状态模式的关键思想是将对象的行为封装在不同的状态对象中,并且在状态转换时可以动态地改变对象的行为。

三、状态模式的核心组件

状态模式的核心组件包括以下几个角色:

  1. Context(上下文):上下文是拥有状态的对象。它定义了客户端感兴趣的接口,并且维护一个当前状态对象,这个状态对象定义了当前的状态和相应的行为。Context 可以通过状态对象来改变它的行为。
  2. State(状态):状态是一个接口或者抽象类,它封装了与 Context 的一个特定状态相关的行为。在 State 接口或者抽象类中定义了所有具体状态类所共享的方法,这些方法的实现将依赖于当前状态。通常,这些方法处理与状态相关的操作,如请求或者事件。
  3. ConcreteState(具体状态):具体状态类实现了 State 接口或者继承了 State 抽象类。每个具体状态类实现了与 Context 的一个状态相关的行为。例如,在电梯系统中,可能会有开门状态、关门状态、运行状态和停止状态等具体状态类。

在这里插入图片描述

这个类图展示了状态模式的核心组成部分:

  • State 接口定义了 doAction(Context) 方法,表示所有具体状态类(OpenState 和 CloseState)需要实现的方法。
  • OpenState 和 CloseState 类分别实现了 State 接口,并实现了 doAction(Context) 方法来处理具体的状态操作。
  • Context 类包含一个状态接口类型的私有成员变量 state,通过 setState(State) 方法设置当前的状态,并通过 request() 方法执行当前状态的动作。

四、运用状态模式

场景假设:我们有一个电灯,它可以被打开和关闭。用户可以通过一个开关来改变电灯的状态。电灯有更多的状态,比如“调暗”、“调亮”、“闪烁”等。

  1. 定义状态接口:首先,我们需要定义一个状态接口,该接口声明了所有具体状态类需要实现的方法。在我们的例子中,我们可以定义一个 LightState 接口,该接口有一个 switchState 方法。

    // 定义状态接口
    public interface LightState {// 声明改变状态的方法,接收一个 Light 对象作为参数void switchState(Light light);
    }
    
  2. 创建具体状态类:然后,我们需要为每种状态创建一个具体的状态类。这些类需要实现状态接口,并实现接口中声明的方法。在我们的例子中,我们可以创建 OnState 和 OffState 类。

    // 创建具体状态类:打开状态
    public class OnState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 DimStatelight.setState(new DimState());System.out.println("Light is dimmed");}
    }// 创建具体状态类:关闭状态
    public class OffState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 OnStatelight.setState(new OnState());System.out.println("Light is turned ON");}
    }// 创建具体状态类:调暗状态
    public class DimState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 BlinkStatelight.setState(new BlinkState());System.out.println("Light is blinking");}
    }// 创建具体状态类:闪烁状态
    public class BlinkState implements LightState {@Overridepublic void switchState(Light light) {// 改变 Light 对象的状态为 OffStatelight.setState(new OffState());System.out.println("Light is turned OFF");}
    }
    
  3. 在上下文类中使用状态:最后,我们需要在上下文类中使用这些状态。上下文类维护一个对状态对象的引用,该引用可以在运行时更改。在我们的例子中,Light 类就是上下文类。

    // 创建上下文类:电灯
    public class Light {// Light 对象维护一个对状态对象的引用private LightState state;public Light() {// 初始状态为 OffStatethis.state = new OffState();}// 设置 Light 对象的状态public void setState(LightState state) {this.state = state;}// 切换 Light 对象的状态public void switchState() {state.switchState(this);}
    }
    
  4. 客户端:通过客户端测试

    public class Client {public static void main(String[] args) {// 创建一个 Light 对象Light light = new Light();// 切换 Light 对象的状态light.switchState(); // 打开电灯light.switchState(); // 调暗电灯light.switchState(); // 电灯开始闪烁light.switchState(); // 关闭电灯}
    }
    

五、状态模式的应用场景

状态模式在许多场景中都非常有用,特别是当一个对象的行为取决于其状态,并且它必须在运行时根据状态改变其行为时。以下是一些常见的应用场景:

  1. 用户界面(UI):在许多用户界面中,元素的行为会根据其状态(如禁用、选中、悬停等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。
  2. 游戏开发:在游戏开发中,角色的行为通常会根据其状态(如站立、跑动、跳跃、攻击等)而改变。使用状态模式,我们可以为每种状态创建一个状态类,使得代码更易于理解和维护。
  3. 工作流引擎:在工作流引擎中,任务的行为会根据其状态(如新建、进行中、已完成等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。
  4. 网络连接:网络连接的行为会根据其状态(如打开、关闭、等待等)而改变。状态模式可以帮助我们管理这些状态,并使状态转换的逻辑更加清晰。

六、小结

状态模式是一种优秀的设计模式,适用于那些对象行为会随着内部状态变化而变化的情况。它通过将对象的状态和行为分离,使得系统更加灵活、易于理解和扩展。

推荐阅读

  1. 深入探究 Spring Boot Starter:从概念到实践
  2. 深入理解 Java 中的 volatile 关键字
  3. OAuth 2.0:现代应用程序的授权标准
  4. Spring 三级缓存
  5. 深入了解 MyBatis 插件:定制化你的持久层框架

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

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

相关文章

snap和apt的区别简单了解

Linux中没有tree命令的时候提示安装的时候出现了两个命令,简单看了看两者有何区别(一般用apt就可以了): sudo snap install tree 和 sudo apt install tree 这两个命令都是用来安装 tree 命令行工具的,但它们使用的是不…

个人博客|PHP源码|支持多国语言切换

一. 前言 今天小编给大家带来了一款可学习,可商用的,支持多国语言的个人博客网站源码,支持二开,无加密。此博客相当简洁,也适合海外。详细界面和功能见下面视频演示。 如果您正好有此需求源码,请联系小编…

开源自动化热键映射工具autohotkey十大用法及精选脚本

AutoHotkey(AHK)是一款功能强大的热键脚本语言工具,它允许用户通过编写脚本来自动化键盘、鼠标等设备的操作,从而极大地提高工作效率。以下是AutoHotkey的十大经典用法,这些用法不仅解放了用户的双手,还展示…

程序化交易广告及其应用

什么是程序化交易广告? 程序化交易广告是以实时竞价技术即RTB(real-time bidding)为核心的广告交易方式。说到这里,你可能会有疑问:像百度搜索关键词广告还有百度网盟的广告,不也是CPC实时竞价的吗&#x…

论文学习_UVSCAN: Detecting Third-Party Component Usage Violations in IoT Firmware

论文名称发表时间发表期刊期刊等级研究单位 Understanding the Security Risks Introduced by Third-Party Components in IoT Firmware 2024年IEEE TDSCCCF A佐治亚理工学院 1. 引言 研究背景:物联网(IoT)已经无处不在,为我们…

HQChart报价列表高级应用教程7-走势列数据对接

HQChart报价列表高级应用教程7-走势列数据对接 走势列小程序效果图PC效果图HQChart代码地址走势列类型配置走势列数据格式示例走势列 单独使用一列显示每个股票的走势图 小程序效果图 PC效果图 HQChart代码地址 地址:github.com/jones2000/HQChart 走势列类型 REPORT_COL…

[工业网络] 模型建立

普渡大学ICS参考模型 普渡企业参考架构(PERA)是由西奥多J威廉姆斯(Theodore J. Williams)和普渡大学计算机集成制造工业大学联盟的成员在1990年代开发的企业架构参考模型。该模型被ISA-99(现为ISA/IEC 62443&#xff…

使用EndNote在Word中插入参考文献,并编辑参考文献样式方法

一、背景 在准备中期报告时,学校给的是Word模板,习惯了Latex排版和添加参考文献的便利后,真不想用word写东西。 之前投《机器人》期刊(被拒了)和准备开题的时候也是用word写的,当时为方便添加参考文献和定…

解决fastjson自动过滤null值

解决fastjson自动过滤null值 使用 SerializerFeature.WriteNullStringAsEmpty 解决 List<HistoryVector> historyVectors new ArrayList<>();HistoryVector historyVector new HistoryVector();historyVector.setInput("1");historyVector.setReason(&q…

计算机操作系统部分选填及大题整理

并发和&#xff08; 共享 &#xff09; 是操作系统的两个最基本的特征,&#xff08; 虚拟 &#xff09;和&#xff08; 异步 &#xff09; 是操作系统的重要特征&#xff0c;并发执行的程序失去可再现性现代操作系统的两个基本特征是&#xff08;程序的并发执行&#xff09;和资…

万界星空科技QMS系统:重塑质量管理新纪元

万界星空科技QMS&#xff08;Quality Management System&#xff09;质量管理系统是一套全面、高效的质量管理工具&#xff0c;旨在帮助企业提升产品质量、优化生产流程、降低质量成本。该系统具备多个具体功能模块&#xff0c;以下是对其主要功能模块的详细介绍&#xff1a; 一…

2024年7月3日 (周三) 叶子游戏新闻

老板键工具来唤去: 它可以为常用程序自定义快捷键&#xff0c;实现一键唤起、一键隐藏的 Windows 工具&#xff0c;并且支持窗口动态绑定快捷键&#xff08;无需设置自动实现&#xff09;。 卸载工具 HiBitUninstaller: Windows上的软件卸载工具 《魅魔》新DLC《Elysian Fields…

​RAG与LLM原理及实践(8)--- Chroma 应用场景及限制

前言 通过前面几节的介绍&#xff0c;你应该对Chroma的运作原理有相当透彻的理解。Chroma的设计正如之前描述的&#xff1a; Chroma提供的工具&#xff1a; 存储文档数据和它们的元数据&#xff1a;store embeddings and their metadata 嵌入&#xff1a;embed documents an…

粗糙度轮廓仪功能简介:一体型轮廓仪功能亮点

在精密制造和质量控制领域&#xff0c;表面粗糙度和轮廓的精确测量是至关重要的。一体型轮廓仪为这一需求提供了全面的解决方案。它采用超高精度纳米衍射光学测量系统、超高直线度研磨级摩擦导轨、高性能直流伺服驱动系统、高性能计算机控制系统技术&#xff0c;为用户提供了一…

使用机器学习,通过文本分析,轻松实现原本复杂的情感分析

01、案例说明 本期分享案例是&#xff1a;文字分析-情感分析&#xff0c;内容是关于某部电影评论好坏的分析&#xff0c;使用大量的已知数据&#xff0c;通过监督学习的方法&#xff0c;可以对于未知的评论进行判断其为正面还是负面的评价。 对于数据分析&#xff0c;原来都是…

Go语言学习:每日一练3

Go语言学习&#xff1a;每日一练3 目录 Go语言学习&#xff1a;每日一练3方法接口继承类型断言 方法 方法是一类有接收者参数的函数。 接收者的类型定义和方法的声明必须在一个包里 type MyInt intfunc (m MyInt) Add(add int) int {return int(m) add } //OR func (m *MyInt)…

巴图制自动化Profinet协议转Modbus协议模块连接PLC和电表通信

1、免编写Modbus轮询程序实现PLC与电表通信的方法 在智能化时代&#xff0c;工业自动控制中的PLC和电表之间的通信是一个常见的需求。传统上&#xff0c;为了使PLC与电表通信&#xff0c;通常需要编写Modbus查询程序来读取和控制数据。然而&#xff0c;使用 巴图制自动化Prof…

235、二叉搜索树的最近公共祖先

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个结点 p、q&#xff0c;最近公共祖先表示为一个结点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自…

用 AI 生成绘本,含大量 prompt

画图过程&#xff0c;为了保证绘本输出的风格统一&#xff0c;角色连贯&#xff0c;画面内容与故事保持一致 1、画风统一的解决办法&#xff1a;固定一个插画师的风格&#xff0c;可以输入插画师的名字&#xff0c;或者垫图&#xff0c;即上传你需要借鉴风格的图片 2、角色连贯…

聚焦西安应博会|2024西安城市安全应急产业展9月精彩呈现

2024西安城市安全应急产业博览会 时间&#xff1a;2024年9月12日-14日 地点&#xff1a;西安国际会展中心 运营&#xff1a;西安西部文化产业博览会有限公司 【展会简介】 为推动安全应急装备向智能化、成套化、专业化方向发展&#xff0c;迎接新质生产力在应急产业新技术…