设计模式之状态机模式

news2024/10/6 12:20:10

一、状态机模式介绍

状态机模式(State Machine Pattern)是一种用于描述对象行为的软件设计模式,属于行为型设计模式。在状态机模式中,对象的行为取决于其内部状态,并且在不同的状态下,对象可能会有不同的行为。这种模式通常涉及定义一组状态以及状态之间的转换规则,从而实现对对象行为的精确控制。

1、状态机模式的基本概念

状态机类图:

状态机模式主要包含以下几个要素:

  1. 状态(State):表示对象所处的特定状态。每个状态都定义了对象在该状态下的行为。
  2. 上下文(Context):上下文是包含状态机的对象。它维护了当前状态,并在状态之间的转换发生时更新状态。
  3. 转换(Transition):描述了对象从一个状态转移到另一个状态的过程。它通常受到一些条件或触发事件的影响。
  4. 动作(Action):动作是状态转换期间可能执行的操作或行为。这些动作可以是更新状态、执行计算、发送消息等。

2、状态机模式的特点

  1. 清晰的状态管理:通过明确定义系统的所有可能状态以及在这些状态之间的转换,帮助开发者清晰地管理和跟踪系统的状态。
  2. 简化复杂逻辑:将复杂的条件分支逻辑转换为状态图,使得逻辑更加直观易懂。
  3. 易于维护和扩展:状态机的结构使得对系统的修改和扩展变得更加容易。通过添加新的状态和转换规则,可以轻松适应需求的变化。
  4. 提高可测试性:由于状态机的行为是预定义的,因此可以更系统地进行测试,有助于确保系统的正确性和可靠性。

3、状态机模式的应用场景

状态机模式在多种应用场景中都有广泛的应用,包括但不限于以下几个方面:

  1. 游戏开发:用于游戏中的角色状态管理,如角色的移动、攻击、防御等状态。
  2. 嵌入式系统:用于描述设备的状态和状态转移,如自动售货机、电梯控制等。
  3. 网络通信:用于管理网络连接的状态,如连接建立、数据传输、连接关闭等。
  4. UI设计:用于管理UI元素的交互逻辑,如按钮的点击状态、表单的输入验证状态等。

二、状态机模式的实现例子

下面是一个简单的Java状态机模式例子。在这个例子中,我们将模拟一个简单的交通信号灯系统,它有三种状态:红灯(Red)、绿灯(Green)、黄灯(Yellow)。每个状态都有一个特定的行为,即打印出当前灯的颜色,并且每个状态都可以转换到下一个状态。

首先,我们定义一个TrafficLightState接口,它表示交通信号灯的所有可能状态:

public interface TrafficLightState {  
    void change(TrafficLightContext context);  
}

然后,我们为每种状态实现这个接口:

public class RedLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("红灯亮");  
        context.setState(new GreenLightState());  
    }  
}  
  
public class GreenLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("绿灯亮");  
        context.setState(new YellowLightState());  
    }  
}  
  
public class YellowLightState implements TrafficLightState {  
    @Override  
    public void change(TrafficLightContext context) {  
        System.out.println("黄灯亮");  
        context.setState(new RedLightState());  
    }  
}

接下来,我们定义TrafficLightContext类,它包含了当前的状态,并且提供了一个方法来改变状态:

public class TrafficLightContext {  
    private TrafficLightState state;  
  
    public TrafficLightContext() {  
        this.state = new RedLightState();  
    }  
  
    public void setState(TrafficLightState state) {  
        this.state = state;  
    }  
  
    public void change() {  
        state.change(this);  
    }  
}

最后,我们创建一个客户端来模拟交通信号灯的状态变化:

public class Client {  
    public static void main(String[] args) {  
        TrafficLightContext context = new TrafficLightContext();  
          
        // 模拟状态变化  
        context.change();  
        context.change();  
        context.change();  
        context.change();  
        context.change();  
    }  
}

在这个例子中,TrafficLightContext类维护了当前的交通信号灯状态,并且提供了一个change方法来改变状态。每个状态类都实现了TrafficLightState接口,并且在其change方法中定义了下一个状态。客户端通过调用TrafficLightContextchange方法来模拟交通信号灯的状态变化。 

现实中的状态转变,比这个复杂多了,一个状态节点可能有多个action操作,类似订单状态的流转,无法直接套用状态机模式,应该有记录状态变迁的全景图(核心要素:当前状态,当前状态可选动作,动作执行后状态迁移)。

以下是一个简单的例子,记录当前状态,可选动作及执行动作后状态的一个例子,用于约束状态的变迁,。

package demo;

import java.util.HashMap;
import java.util.Map;

public class StateMachine {

	/**
	 * key:当前状态 ,value: Map<String, String>,可选的动作及后续状态,key:xxxAction,value:nextState
	 */
	private Map<String, Map<String, String>> stateMap;

	public StateMachine() {
		stateMap = new HashMap<String, Map<String, String>>();

		// 初始状态可以执行的Action及执行后的动作
		Map<String, String> initActionMap = new HashMap<String, String>();
		initActionMap.put("runAction", "run");
		stateMap.put("init", initActionMap);

		// run状态下可以执行的动作
		Map<String, String> runActionMap = new HashMap<String, String>();
		runActionMap.put("stopAction", "stop");
		runActionMap.put("sleepAction", "sleep");
		runActionMap.put("endAction", "end");
		stateMap.put("run", runActionMap);

		// sleep状态下可以执行的动作
		Map<String, String> sleepActionMap = new HashMap<String, String>();
		sleepActionMap.put("runAction", "run");
		stateMap.put("sleep", sleepActionMap);

		// stop状态下可以执行的动作
		Map<String, String> stopActionMap = new HashMap<String, String>();
		stopActionMap.put("runAction", "run");
		stateMap.put("stop", stopActionMap);

	}

	public String getNextState(String curState, String action) {
		Map<String, String> curStateMap = stateMap.get(curState);
		if (curStateMap == null) {
			System.out.println("curState error");
			return "";
		}

		String nextState = curStateMap.get(action);
		if (nextState == null) {
			System.out.println("acction error");
			return "";
		}
		return nextState;
	}

	public static void main(String[] args) {
		StateMachine sm = new StateMachine();
		String nextState = sm.getNextState("init", "runAction");
		System.out.println(nextState);
		nextState = sm.getNextState("run", "stopAction");
		System.out.println(nextState);
		nextState = sm.getNextState("stop", "runAction");
		System.out.println(nextState);
		nextState = sm.getNextState("run", "endAction");
		System.out.println(nextState);
	}

}

三、总结

        状态机模式是一种强大的工具,能够帮助开发者在软件开发中处理复杂的逻辑和状态管理问题。通过明确定义系统的状态和转换规则,状态机模式使得系统的行为更加清晰、可控和易于维护。同时,状态机模式还具有广泛的应用场景和灵活的实现方式,适用于多种复杂的软件开发需求。

如果状态模式对你有用,记得点赞收藏。

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

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

相关文章

RAG 案框架(Qanything、RAGFlow、FastGPT、智谱RAG)对比

各家的技术方案 有道的QAnything 亮点在&#xff1a;rerank RAGFLow 亮点在&#xff1a;数据处理index 智谱AI 亮点在文档解析、切片、query改写及recall模型的微调 FastGPT 优点&#xff1a;灵活性更高 下面分别按照模块比较各框架的却别 功能模块QAnythingRAGFLowFastG…

【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统一引用格式

不同类型的链表 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 不同类型…

Day05-04-持续集成总结

Day05-04-持续集成总结 1. 持续集成2. 代码上线目标项目 1. 持续集成 git 基本使用, 拉取代码,上传代码,分支操作,tag标签 gitlab 用户 用户组 项目 , 备份,https,优化. jenkins 工具平台,运维核心, 自由风格工程,maven风格项目,流水线项目, 流水线(pipeline) mavenpom.xmlta…

Android 10年,35岁,该往哪个方向发力

网上看到个网友发的帖子&#xff0c;觉的这个可能是很多开发人员都会面临和需要思考的问题。 不管怎样&#xff0c; 要对生活保持乐观&#xff0c;生活还是有很多的选择和出路的。 &#xff08;内容来自网络&#xff0c;不代表个人观点&#xff09; 《Android Camera开发入门》…

关闭vue3中脑瘫的ESLine

在创建vue3的时候脑子一抽选了ESLine,然后这傻卵子ESLine老是给我报错 博主用的idea开发前端 ,纯粹是用不惯vscode 关闭idea中的ESLine,这个只是取消红色波浪线, 界面中的显示 第二步,在vue.config.js中添加 lintOnSave: false 到这里就ok了,其他的我试过了一点用没有

专业140+总分420+天津大学815信号与系统考研经验天大电子信息与通信工程,真题,大纲,参考书。

顺利上岸天津大学&#xff0c;专业课815信号与系统140&#xff0c;总分420&#xff0c;总结一些自己的复习经历&#xff0c;希望对于报考天大的同学有些许帮助&#xff0c;少走弯路&#xff0c;顺利上岸。专业课&#xff1a; 815信号与系统&#xff1a;指定教材吴大正&#xf…

飞书 API 2-4:如何使用 API 将数据写入数据表

一、引入 上一篇创建好数据表之后&#xff0c;接下来就是写入数据和对数据的处理。 本文主要探讨数据的插入、更新和删除操作。所有的操作都是基于上一篇&#xff08;飞书 API 2-4&#xff09;创建的数据表进行操作。上面最终的数据表只有 2 个字段&#xff1a;序号和邮箱。序…

(完整音频)DockerHub、OpenAI、GitCode,脱钩时代,我们该如何自处?

本期主播 朱峰&#xff1a;「津津乐道播客网络」创始人&#xff0c;产品及技术专家。&#xff08;微博&#xff1a;zhufengme&#xff09;高春辉&#xff1a;「科技乱炖」主播。“中国互联网站长第一人”&#xff0c;科技、互联网领域的连续创业者。&#xff08;微博&#xff1…

SCI一区TOP|准随机分形搜索算法(QRFS)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;LA Beltran受到分形几何、低差异序列启发&#xff0c;提出了准随机分形搜索算法&#xff08;Quasi-random Fractal Search, QRFS&#xff09;。 2.算法原理 2.1算法思…

内容营销专家刘鑫炜:网站排名需考虑哪些SEO优化技巧?

网站排名的SEO优化技巧包括&#xff1a; 1. 关键词研究&#xff1a;了解目标受众的搜索关键词&#xff0c;将这些关键词合理地应用在网站的标题、描述、正文和标签中&#xff0c;有助于提高网站排名。 2. 内容优化&#xff1a;创建高质量、有价值的内容&#xff0c;可以吸引搜…

【leetcode52-55图论、56-63回溯】

图论 回溯【56-63】 46.全排列 class Solution:def permute(self, nums):result []self.backtracking(nums, [], [False] * len(nums), result)return resultdef backtracking(self, nums, path, used, result):if len(path) len(nums):result.append(path[:])returnfor i …

【HBZ】高性能zeroCopy零拷贝与普通IO差距与原理

简介 随着IO不断地发展&#xff0c;无论哪种拷贝方式&#xff0c;DMA从磁盘拷贝数据到内核缓冲区&#xff0c;都会拷贝多一些数据, 不会只拷贝用户态的指定size的数据&#xff0c;而是会将目标数据的临近数据也都拷贝到内核缓冲区&#xff0c;以便下次IO操作可以直接从内核缓冲…

【python】python客户信息审计风险决策树算法分类预测(源码+数据集+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

unity3d:Shader知识点,矩阵,函数,坐标转换,Tags,半透明,阴影,深度,亮度,优化

基本结构 Shader "MyShaderName" {Properties {// 属性}SubShader {// 针对显卡A的SubShaderPass {// 设置渲染状态和标签Tags { "LightMode""ForwardBase" }// 开始Cg代码片段CGPROGRAM// 该代码片段的编译指令&#xff0c;例如&#xff1a;#p…

浪潮信息元脑服务器支持英特尔®至强®6能效核处理器 展现强劲性能

如今&#xff0c;服务器作为数字经济的核心基础设施&#xff0c;正面临着前所未有的挑战和机遇。作为服务器领域的领军企业&#xff0c;浪潮信息始终站在行业前沿&#xff0c;不断推陈出新&#xff0c;以满足客户日益增长的需求。近日&#xff0c;浪潮信息再次展现技术实力&…

Java学习十四—Java8特性之Lambda表达式

一、简介 Java 8 引入了 Lambda 表达式&#xff0c;它是一种更简洁、更便于使用的函数式编程特性。Lambda 表达式允许将函数作为方法的参数&#xff08;函数式接口的实例&#xff09;传递给某个方法&#xff0c;或者将代码像数据一样进行传递。 ‍ lambda是一个匿名函数&#…

Kubernetes分享

幂等性(Idempotency) 介绍 简单来说&#xff0c;幂等性幂等性(Idempotency)是计算机科学中的一个重要概念&#xff0c;特别是在分布式系统和网络应用中。指的是某个操作可以重复执行多次&#xff0c;但其结果是相同的&#xff0c;不会因为多次执行而改变系统的状态。 https://…

解决后端限制导致前端配置跨域仍请求失败报504的问题

文章目录 问题一、通过配置跨域方式二、直接真实接口请求三、解决方式四、后端这样做的原因 总结 问题 前端项目设置跨域proxy处理&#xff0c;接口请求不会报跨域&#xff0c;但是接口请求报了504&#xff0c;这种情况如何处理呢&#xff0c;后端又为何要这么做&#xff0c;下…

2007-2022年中国各企业数字化转型与供应链效率

企业数字化转型与供应链效率是现代企业管理和发展的两个关键方面。以下是对中国各企业数字化转型与供应链效率数据的介绍&#xff1a; 数据简介 企业数字化转型&#xff1a;指企业通过采用数字技术与创新方法&#xff0c;改造业务流程、组织结构和产品服务&#xff0c;以提升…

U盘非安全拔出后的格式化危机与数据拯救策略

在数字化时代&#xff0c;U盘作为便捷的数据携带工具&#xff0c;其重要性不言而喻。然而&#xff0c;许多用户在日常使用中往往忽视了安全退出的重要性&#xff0c;直接拔出U盘后再插入时可能会遭遇“需要格式化”的提示&#xff0c;这一状况不仅令人措手不及&#xff0c;更可…