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

embedded/2025/1/24 17:54:13/

一、什么是状态模式

        什么是状态模式呢,这里我举一个例子来说明,在自动挡汽车中,挡位的切换是根据驾驶条件(如车速、油门踏板位置、刹车状态等)自动完成的。这种自动切换挡位的过程可以很好地用状态模式来描述。状态模式(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.ppmy.cn/embedded/156628.html

相关文章

数据库性能优化(sql优化)_索引详解04_深入理解B+树_yxy)

数据库性能优化_深入理解B+树 1 通过代码方式解释B+树1.1 查找操作1.2 插入操作1.3 删除操作1.4 更新操作2 组合索引的查找逻辑2.1 等值查找2.1 范围查找1 通过代码方式解释B+树 B树索引在增删改操作时,底层结构会发生相应的变化,以保持树的平衡和有序性。 下面通过简单的伪…

基于亿坊PHP框架构建物联网解决方案的优势分析!

在物联网 (IoT) 领域&#xff0c;选到合适的框架对于整个项目的开展也尤为重要。通常情况下&#xff0c;基于PHP的一些主流框架被用户常选择&#xff0c;今天就带大家了解下基于亿坊PHP框架构建物联网解决方案的优势有哪些&#xff1f; 1、开发效率高 在物联网项目中&#xf…

pandas基础:基本数据结构

基本数据结构 pandas中具有两种基本的数据存储结构&#xff0c;存储一维values的Series和存储二维values的DataFrame&#xff0c;在这两种结构上定义了很多的属性和方法。 Series Series一般由四个部分组成&#xff0c;分别是序列的值data、索引index、存储类型dtype、序列的…

C++并发编程之提高C++多线程应用可测试性的思想和方法

提高C多线程应用的可测试性是一个重要的课题&#xff0c;因为多线程应用程序通常比单线程应用程序更复杂&#xff0c;更容易出现难以复现的并发问题。为了确保多线程应用的可靠性和正确性&#xff0c;可以采用以下思想和方法来提高其可测试性。 1. 模块化设计 将多线程应用分…

WPF MVVM 模式如何监听IsVisibleChanged 事件

原本以为这是一个很简单的问题&#xff0c;但是我却走了不少的弯路。记录下来自省。 我使用的是库System.Windows.Interactivity.dll&#xff0c;首先在xaml 中使用了EventTrrigger <!-- 当 IsVisibleChanged 事件触发时&#xff0c;执行绑定的命令 --> <!--<…

HarmonyOS Next 应用UI生成工具介绍

背景 HarmonyOS Next适配开发过程中难买难要参考之前逻辑&#xff0c;但是可能时间较长文档不全&#xff0c;只能参考Android或iOS代码&#xff0c;有些逻辑较重的场景还可以通过AI工具将Android 的Java代码逻辑转成TS完成部分复用。对于一些UI场景只能手动去写&#xff0c;虽…

Excel-XLOOKUP-返回指定范围的数据

XLOOKUP(lookup_value, lookup_array, return_array, [if_not_found], [match_mode], [search_mode]) 第一参数lookup_value是必需参数&#xff0c;指定需要查询的值&#xff1b; 第二参数lookup_array是必需参数&#xff0c;指定查询的单元格区域或数组&#xff1b; 第三参数…

ChromeOS 132 版本更新

ChromeOS 132 版本更新 1. 企业定制化 Chrome Web Store 管理员现在可以使用新设置定制 Chrome Web Store 以适应他们管理的用户&#xff0c;包括以下功能&#xff1a; 添加公司标志添加首页横幅和自定义公告策划扩展集合实施基于类别的控制 这些设置可以通过管理员控制台进…