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

一、什么是状态模式

        什么是状态模式呢,这里我举一个例子来说明,在自动挡汽车中,挡位的切换是根据驾驶条件(如车速、油门踏板位置、刹车状态等)自动完成的。这种自动切换挡位的过程可以很好地用状态模式来描述。状态模式(State Pattern) 是一种行为型设计模式,它允许一个对象在其内部状态发生变化时(加速或者减速)改变其行为(换挡)。状态模式的核心思想是将对象的行为封装在不同的状态类中,使得对象的行为随着状态的改变而改变。这种模式特别适用于对象的行为依赖于其内部状态的场景。

二、为什么使用状态模式

  1. 清晰的职责划分:代码结构清晰,每个状态类的职责单一,易于理解和维护。例如,在自动挡汽车中,每个挡位的行为都封装在独立的状态类中,职责划分明确。

  2. 动态改变行为:减少了复杂的条件分支(如 if-elseswitch-case),使代码更加简洁和可读。例如,在自动挡汽车中,换挡逻辑由状态机自动处理,无需在主逻辑中写复杂的条件判断。

  3. 扩展性:符合开闭原则(对扩展开放,对修改封闭)。例如,在自动挡汽车中,新增一个挡位(如6挡)时,只需添加一个新的状态类,无需修改现有的换挡逻辑。

  4. 低耦合:状态类和上下文类之间的依赖关系减少,提高了代码的灵活性和可维护性。例如,在自动挡汽车中,Car 类与各个挡位状态类通过 GearState 接口交互,降低了耦合度。

  5. 适应复杂状态逻辑:能够清晰地表达状态转换逻辑,避免代码混乱。例如,在自动挡汽车中,换挡逻辑可能涉及多种条件(如车速、油门位置等),状态机模式能够清晰地表达这些逻辑。

三、状态模式的示例

3.1 状态模式示例及角色

1. State:定义状态接口(行为)

定义了所有挡位状态的通用接口,包含所有挡位共有的方法,例如加速、减速等

public interface GearState {void accelerate(Car car); // 加速时的行为void decelerate(Car car); // 减速时的行为
}

2. ConcreteState:实现具体状态类(档位)

每个挡位(如1挡、2挡、3挡、4挡、5挡等)都实现状态接口,并定义在该挡位下的行为。

public class FirstGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前1档:加速...");car.setState(new SecondGear()); // 切换到2挡}@Overridepublic void decelerate(Car car) {System.out.println("当前1档:减速...");car.setState(new NeutralGear()); // 切换到空挡}
}public class SecondGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前2档:加速...");car.setState(new ThirdGear()); // 切换到3挡}@Overridepublic void decelerate(Car car) {System.out.println("当前2档:减速...");car.setState(new FirstGear()); // 切换到1挡}
}public class ThirdGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前3档:加速...");car.setState(new FourthGear()); // 切换到4挡}@Overridepublic void decelerate(Car car) {System.out.println("当前3档:减速...");car.setState(new SecondGear()); // 切换到2挡}
}public class FourthGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前4档:加速...");car.setState(new FifthGear()); // 切换到5挡}@Overridepublic void decelerate(Car car) {System.out.println("当前1档:减速...");car.setState(new ThirdGear()); // 切换到3挡}
}public class FifthGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前5档:加速...");// 保持在5挡}@Overridepublic void decelerate(Car car) {System.out.println("当前5档:减速...");car.setState(new FourthGear()); // 切换到4挡}
}public class NeutralGear implements GearState {@Overridepublic void accelerate(Car car) {System.out.println("当前空档:加速...");car.setState(new FirstGear()); // 切换到1挡}@Overridepublic void decelerate(Car car) {System.out.println("当前空档:减速...");// 保持在空挡}
}

3、Context(上下文):(当前车辆,记录当前状态)

上下文可以被视为汽车的驾驶系统,它包含当前挡位的状态,并根据驾驶员的操作切换挡位

public class Car {private GearState currentState;public Car() {this.currentState = new NeutralGear(); // 初始状态为空挡}public void setState(GearState state) {this.currentState = state;}public void accelerate() {currentState.accelerate(this);}public void decelerate() {currentState.decelerate(this);}
}

4、场景(开车)

public class Main {public static void main(String[] args) {Car car = new Car();car.accelerate(); // 初始状态为空挡,加速后切换到1挡car.accelerate(); // 当前状态为1挡,加速后切换到2挡car.accelerate(); // 当前状态为2挡,加速后切换到3挡car.decelerate(); // 当前状态为3挡,减速后切换到2挡car.decelerate(); // 当前状态为2挡,减速后切换到1挡car.decelerate(); // 当前状态为1挡,减速后切换到空挡}
}//输出
当前0档:加速...
当前1档:加速...
当前2档:加速...
当前3档:加速...
当前3档:减速...
当前2档:减速...
当前1档:减速...
当前0档:减速...

3.2 在JAVA开发中常用的Spring状态机

        在Spring框架中,可以使用Spring State Machine来实现状态机模式。Spring State Machine是一个功能强大的状态机框架,支持定义状态、事件和状态转换,并且可以与Spring生态系统无缝集成。在实际开发中,可能使用Spring框架比较多,一般都是直接使用现成的Spring State Machine 来实现状态模式。

1、集成依赖包

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.1.3.RELEASE</version>
</dependency>

2、定义状态和事件

//车辆档位枚举类
public enum CarState {NEUTRAL,     //空挡FIRST_GEAR,  //一档SECOND_GEAR, //二挡THIRD_GEAR,  //三挡FOURTH_GEAR, //四挡FIFTH_GEAR;   //五档
}//车辆行为枚举类
public enum CarEvent {ACCELERATE,     //加速行为DECELERATE;     //减速行为
}

3、配置状态机

@Configuration
@EnableStateMachine(name="carStateMachine")
public class CarStateMachineConfig extends StateMachineConfigurerAdapter<CarState, CarEvent> {public void configure(StateMachineStateConfigurer<CarState, CarEvent> states) throws Exception {states.withStates().initial(CarState.NEUTRAL).states(EnumSet.allOf(CarState.class));}@Overridepublic void configure(StateMachineTransitionConfigurer<CarState, CarEvent> states) throws Exception {states.withExternal().source(CarState.NEUTRAL).target(CarState.FIRST_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FIRST_GEAR).target(CarState.SECOND_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.SECOND_GEAR).target(CarState.THIRD_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.THIRD_GEAR).target(CarState.FOURTH_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FOURTH_GEAR).target(CarState.FIFTH_GEAR).event(CarEvent.ACCELERATE).and().withExternal().source(CarState.FIFTH_GEAR).event(CarEvent.ACCELERATE) // No change.and().withExternal().source(CarState.FIFTH_GEAR).target(CarState.FOURTH_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.FOURTH_GEAR).target(CarState.THIRD_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.THIRD_GEAR).target(CarState.SECOND_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.SECOND_GEAR).target(CarState.FIRST_GEAR).event(CarEvent.DECELERATE).and().withExternal().source(CarState.FIRST_GEAR).target(CarState.NEUTRAL).event(CarEvent.DECELERATE);}// 配置状态机持久化@Beanpublic DefaultStateMachinePersister machinePersister() {return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Car>() {@Overridepublic void write(StateMachineContext<Object, Object> stateMachineContext, Car car) throws Exception {//持久化操作。可以通过任何形式进行持久化。redis 、 mongodb、mysql,ecache}@Overridepublic StateMachineContext<Object, Object> read(Car car) throws Exception {// 从持久化组件里进行读取return new DefaultStateMachineContext(car.getCarState(), null, null, null);}});}
}

4、定义状态监听器

        在Spring State Machine中,可以通过@WithStateMachine注解和@OnTransition注解来定义状态监听器。这些监听器会在状态转换时被触发。

// 监听器是监听到 action 后进行状态的一个变更。
@Slf4j
@Component("carStateListener")
@WithStateMachine(name="carStateMachine")
public class CarStateListener {@OnTransition(source = "NEUTRAL", target = "FIRST_GEAR")public boolean onAccelerateFromNeutral(Message<CarEvent> message) {log.info("Accelerating from NEUTRAL to FIRST_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIRST_GEAR);return true;}@OnTransition(source = "FIRST_GEAR", target = "SECOND_GEAR")public boolean onAccelerateFromFirstGear(Message<CarEvent> message) {log.info("Accelerating from FIRST_GEAR to SECOND_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.SECOND_GEAR);return true;}@OnTransition(source = "SECOND_GEAR", target = "THIRD_GEAR")public boolean onAccelerateFromSecondGear(Message<CarEvent> message) {log.info("Accelerating from SECOND_GEAR to THIRD_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.THIRD_GEAR);return true;}@OnTransition(source = "THIRD_GEAR", target = "FOURTH_GEAR")public boolean onAccelerateFromThirdGear(Message<CarEvent> message) {log.info("Accelerating from THIRD_GEAR to FOURTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FOURTH_GEAR);return true;}@OnTransition(source = "FOURTH_GEAR", target = "FIFTH_GEAR")public boolean onAccelerateFromFourthGear(Message<CarEvent> message) {log.info("Accelerating from FOURTH_GEAR to FIFTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIFTH_GEAR);return true;}@OnTransition(source = "FIFTH_GEAR", target = "FOURTH_GEAR")public boolean onDecelerateFromFifthGear(Message<CarEvent> message) {log.info("Decelerating from FIFTH_GEAR to FOURTH_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FOURTH_GEAR);return true;}@OnTransition(source = "FOURTH_GEAR", target = "THIRD_GEAR")public boolean onDecelerateFromFourthGear(Message<CarEvent> message) {log.info("Decelerating from FOURTH_GEAR to THIRD_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.THIRD_GEAR);return true;}@OnTransition(source = "THIRD_GEAR", target = "SECOND_GEAR")public boolean onDecelerateFromThirdGear(Message<CarEvent> message) {log.info("Decelerating from THIRD_GEAR to SECOND_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.SECOND_GEAR);return true;}@OnTransition(source = "SECOND_GEAR", target = "FIRST_GEAR")public boolean onDecelerateFromSecondGear(Message<CarEvent> message) {log.info("Decelerating from SECOND_GEAR to FIRST_GEAR");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.FIRST_GEAR);return true;}@OnTransition(source = "FIRST_GEAR", target = "NEUTRAL")public boolean onDecelerateFromFirstGear(Message<CarEvent> message) {log.info("Decelerating from FIRST_GEAR to NEUTRAL");Car car = (Car) message.getHeaders().get("car");car.setCarState(CarState.NEUTRAL);return true;}}

4、使用状态机

@Service
public class CarService {@Resourceprivate StateMachine<CarState, CarEvent> carStateMachine;@Resourceprivate StateMachinePersister<CarState, CarEvent, Car> carMachinePersister;//模拟一个存储private Car car = new Car();//加速方法public Car acc() {if (car.getCarState() == null){car.setCarState(CarState.NEUTRAL);}// 书写逻辑Message message = MessageBuilder.withPayload(CarEvent.ACCELERATE).setHeader("car", car).build();if(changeStateAction(message,car)) {return car;}return car;}//减速方法public Car dece() {if (car.getCarState() == null){car.setCarState(CarState.NEUTRAL);}// 书写逻辑Message message = MessageBuilder.withPayload(CarEvent.DECELERATE).setHeader("car", car).build();if(changeStateAction(message,car)) {return car;}return car;}private boolean changeStateAction(Message<CarEvent> message, Car car) {try {carStateMachine.start();//尝试恢复状态机状态carMachinePersister.restore(carStateMachine, car); // 待议boolean res = carStateMachine.sendEvent(message);//持久化状态机状态carMachinePersister.persist(carStateMachine, car); // 持久return res;} catch (Exception e) {e.printStackTrace();} finally {carStateMachine.stop();}return false;}
}

4、场景(开车)

@SpringBootApplication
public class CarApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(DesignApplication.class, args);CarService carService = context.getBean(CarService.class);Car car;car = carService.acc(); // 初始状态为空挡,加速后切换到1挡System.out.println("After accelerate: " + car.getCarState());car = carService.acc(); // 当前状态为1挡,加速后切换到2挡System.out.println("After accelerate: " + car.getCarState());car = carService.dece(); // 当前状态为2挡,减速后切换到1挡System.out.println("After decelerate: " + car.getCarState());car = carService.dece(); // 当前状态为1挡,减速后切换到空挡System.out.println("After decelerate: " + car.getCarState());}
}//输出
After accelerate: FIRST_GEAR
After accelerate: SECOND_GEAR
After decelerate: FIRST_GEAR
After decelerate: NEUTRAL

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

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

相关文章

CTF随题思路—简单的base编码

打开是一大段base64编码&#xff0c;多次解码后再用base92解码

顺序表和链表(详解)

线性表 线性表&#xff08; linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线。…

vxe-table和element表尾合计行

1、vxe-table vxe-table的表尾合计&#xff0c;需要show-footer和footer-method搭配使用。 <vxe-table:data"tableData"ref"vxeRef"border resizable :footer-method"footerMethod":show-footer"true" >…

Grafana系列之Dashboard:新增仪表板、新增变量、过滤变量、变量查询、导入仪表板、变量联动、Grafana Alert

概述 关于Prometheus和Grafana的安装&#xff0c;略过。 写在前面 Dashboard&#xff1a;仪表板&#xff0c;可包含多个PanelPanel&#xff1a;面板&#xff0c;Dashboard中的组件 如有写得不对的地方&#xff0c;烦请指出。 新增仪表板 点击右上角的 选择New dashboard…

使用 Ansys Discovery 对离心风机进行仿真

了解设置模拟并获得有用结果的步骤。 离心风机&#xff1a;基础知识和重要性 离心风机&#xff0c;也称为径流式风机&#xff0c;是旨在通过将动能转化为势能来增加空气或气体的压力和流量的机械装置。它们的工作原理是利用旋转叶轮产生的离心力轴向吸入空气&#xff0c;然后…

客户案例:向导ERP与金蝶云星空集成方案

一、客户背景 该客户公司主要致力于黄金、铂金、金镶玉首饰的研发设计、生产加工、批发及直营加盟业务。公司总部占地面积目前已达6000多平方米&#xff0c;拥有标准生产厂房和现代化生产设施&#xff0c;拥有一支完善的企业管理团队和专业技工队伍。 该企业目前同时采用向导 E…

机器学习-K近邻算法

文章目录 一. 数据集介绍Iris plants dataset 二. 代码三. k值的选择 一. 数据集介绍 鸢尾花数据集 鸢尾花Iris Dataset数据集是机器学习领域经典数据集&#xff0c;鸢尾花数据集包含了150条鸢尾花信息&#xff0c;每50条取自三个鸢尾花中之一&#xff1a;Versicolour、Setosa…

【豆包MarsCode蛇年编程大作战】花样贪吃蛇

目录 引言 展示效果 prompt提示信息 第一次提示&#xff08;实现基本功能&#xff09; 初次实现效果 第二次提示&#xff08;美化UI&#xff09; 第一次美化后的效果 第二次美化后的效果 代码展示 实现在线体验链接 码上掘金使用教程 体验地址&#xff1a; 花样贪吃蛇…

小白爬虫——selenium入门超详细教程

目录 一、selenium简介 二、环境安装 2.1、安装Selenium 2.2、浏览器驱动安装 三、基本操作 3.1、对页面进行操作 3.1.1、初始化webdriver 3.1.2、打开网页 3.1.3、页面操作 3.1.4、页面数据提取 3.1.5、关闭页面 ?3.1.6、综合小案例 3.2、对页面元素进行操作 3…

U3D的.Net学习

Mono&#xff1a;这是 Unity 最初采用的方式&#xff0c;它将 C# 代码编译为中间语言 (IL)&#xff0c;然后在目标平台上使用虚拟机 (VM) 将其转换为本地机器码执行。 IL2CPP&#xff1a;这是一种较新的方法&#xff0c;它会将 C# 代码先编译为 C 代码&#xff0c;再由 C 编译器…

Java集合学习:HashMap的原理

一、HashMap里的Hash是什么&#xff1f; 首先&#xff0c;我们先要搞清楚HashMap里的的Hash是啥意思。 当我们在编程过程中&#xff0c;往往需要对线性表进行查找操作。 在顺序表中查找时&#xff0c;需要从表头开始&#xff0c;依次遍历比较a[i]与key的值是否相等&#xff…

SOAFEE 技术研讨会:汽车软件定义与自动驾驶技术探讨

在本次技术研讨会上&#xff0c;来自汽车与科技领域的专家们围绕汽车软件定义及自动驾驶技术展开了深入交流与探讨。从 SOAFEE 蓝图计划的创新性理念&#xff0c;到 Autoware 开源项目及 Open AD Kit 在实际应用中的探索&#xff0c;再到 Edge Workload Abstraction and Orches…

FastJson很快,有什么用?

FastJson 在国内的热度还是挺高的&#xff0c;受到了很多开发者的喜欢。不过&#xff0c;我自己倒没有在项目中用过。我记得刚工作那会新做的一个项目有明确规定禁止使用 FastJson。 昨天看到一篇关于 FastJson 的文章&#xff0c;这位朋友分享了自己在使用 FastJson 遇到的一…

Jetson nano 安装 PCL 指南

本指南帮助 ARM64 架构的 Jetson Nano 安装 PCL&#xff08;点云库&#xff09;。 安装步骤 第一步&#xff1a;安装依赖 在终端中运行以下命令&#xff0c;安装 PCL 所需的依赖&#xff1a; sudo apt-get update sudo apt-get install git build-essential linux-libc-dev s…

ansible自动化运维实战--软件包管理模块、服务模块、文件模块和收集模块setup(4)

文章目录 一、软件包管理模块1.1、功能1.2、常用参数1.3、示例 二、服务模块2.1、功能2.2、服务模块常用参数2.3、示例 三、文件与目录模块3.1、file功能3.2、常用参数3.3、示例 四、收集模块-setup4.1、setup功能4.2、示例 一、软件包管理模块 1.1、功能 Ansible 提供了多种…

终极的复杂,是简单

软件仿真拥有最佳的信号可见性和调试灵活性,能够高效捕获很多显而易见的常见错误,被大多数工程师熟练使用。 空间领域应用的一套数据处理系统(Data Handling System),采用抗辐FPGA作为主处理器,片上资源只包含10752个寄存器,软仿也是个挺花时间的事。 Few ms might take …

开关电源设计(2)–BUCK电路设计和计算过程

BUCK电路也即降压电路&#xff0c;是应用最广泛的DC-DC变换器 需求决定的参数 V i 和 V o V_{i} 和V_{o} Vi​和Vo​ f f f I o I_{o} Io​ 输出电压纹波率 效率 需要计算:电感量 r r r 占空比 C 参数计算&#xff1a; 当MOS管导通时&#xff0c;电感电压 V O N V i − …

cudatex文本编辑器

一、下载 通过网盘分享的文件&#xff1a;cudatext 链接: https://pan.baidu.com/s/1TZbGk3AM09SuKvvcQy0d6Q?pwdbbzd 提取码: bbzd 本链接分享的为2025年1月下载上传的软件&#xff0c;版本为1.220.6.1 &#xff1b;软件皆已放入中文包。 二、设置中文简体 打开 https://…

C语言文件操作:标准库与系统调用实践

目录 1、C语言标准库文件操作 1.1.题目要求&#xff1a; 1.2.函数讲解&#xff1a; fopen 函数原型 参数 常用的打开模式 返回值 fwrite函数 函数原型 参数 返回值 注意事项 fseek函数 函数原型 参数 返回值 fread函数 函数原型 参数 返回值 fclose 函数…

一款专业通用开源的MES生产执行管理系统

系统简介 MES系统是一款B/S结构、开源、免费的生产执行管理系统。 此系统基于本人多年离散智造行业的业务经验及J2EE项目经验开发。 主要目的是为国内离散制造业的中小企业提供一个专业化、通用性、低成本的MES系统解决方案。 系统将提供“售前”、“实施”、“用户培训”、…