状态机笔记

文章目录

听到这个名词一愣,但是很快反应过来了,就是状态和逻辑控制名词化了。

当然,和普通逻辑相比,可不是改个名字而已,有很多不同。

什么是状态机

Java状态机是一种用于描述系统状态转换的模型,通过定义状态、事件、动作和转换规则来控制程序行为。

其核心要素如下:

**状态(States):**系统可能处于的固定状态,如订单状态中的"已支付"、"已发货"等 。 ‌

**事件(Events):**触发状态转换的外部或内部信号,如"支付"、"取消"等操作 。 ‌

**动作(Actions):**状态转换时执行的操作,例如更新状态字段或记录日志 。 ‌

**转换(Transitions):**定义事件触发下状态转移的规则,例如"支付成功"事件将"待支付"状态转为"支付成功"。

这么看是否还得维护个状态表,看起来才比较清楚。

普通逻辑和状态机的区别

名称 普通逻辑 状态机
逻辑清晰度 需要if else来实现逻辑判断,可读性差 状态机通过预定义状态和事件,将状态转换规则显式化,避免冗余的条件判断,可读性强。
扩展性 需要在原代码上修改逻辑,易出错,扩展性差。 新增状态或事件时,只需扩展状态机配置,无需修改现有代码。
线程安全支持 需手动处理同步问题(如使用synchronized或Lock),实现复杂且易出错。 状态机框架(如Spring StateMachine)内置线程同步机制,确保并发场景下状态一致性。
业务解耦 状态处理常耦合在业务方法内,难以独立测试。 ‌ 状态机将状态逻辑与业务代码分离,便于测试和复用。
可视化配置 普通逻辑需通过代码硬编码状态转换,可读性差。 ‌ 框架支持通过代码或配置文件定义状态机,直观展示状态迁移路径。

集成及使用

引入maven依赖

xml 复制代码
<dependency>
	<groupId>org.springframework.statemachine</groupId>
	<artifactId>spring-statemachine-core</artifactId>
	<version>2.0.0.RELEASE</version>
</dependency>
<!-- uml to code -->
<dependency>
	<groupId>org.springframework.statemachine</groupId>
	<artifactId>spring-statemachine-uml</artifactId>
	<version>2.0.0.RELEASE</version>
</dependency>	
定义状态枚举

代码:

java 复制代码
public enum States {
    UNPAID,                 // 待支付
    WAITING_FOR_RECEIVE,    // 待收货
    DONE                   	// 结束
}
定义事件枚举

代码:

java 复制代码
public enum Events {
    PAY,        // 支付
    RECEIVE     // 收货
}

初始化订单的状态集合以及状态转移事件

代码:

java 复制代码
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {
 
    private Logger LOGGER = LoggerFactory.getLogger(getClass());
 
    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));
    }
    
    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
            throws Exception {
        transitions
             .withExternal()
                .source(States.UNPAID).target(States.WAITING_FOR_RECEIVE)
                .event(Events.PAY)
                .and()   
            .withExternal()
                .source(States.WAITING_FOR_RECEIVE).target(States.DONE)
                .event(Events.RECEIVE);
    }
        //守护
    @Bean	
    public Guard<States, Events> guard() {
        return new Guard<States, Events>() {
            public boolean evaluate(StateContext<States, Events> context) {
                return true;
            }
        };
}
状态转移的监听器
java 复制代码
@WithStateMachine
public class EventListener {
	private Logger LOGGER = LoggerFactory.getLogger(getClass());
	
    @OnTransition(target = "UNPAID")  
    public void create() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------订单创建,待支付-----------------------");  
    }  
    
    @OnTransition(source = "UNPAID", target = "WAITING_FOR_RECEIVE")  
    public void pay() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------用户完成支付,待收货--------------------");  
    }  
    
    @OnTransition(source = "WAITING_FOR_RECEIVE", target = "DONE")  
    public void receive() {  
    	//此处可以执行具体业务逻辑处理
    	LOGGER.info("--------------------用户已收货,订单完成----------------------");  
    }  
 
}
测试

测试类代码:

java 复制代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
 
	@Test
	public void contextLoads() {
	}
 
	@Autowired
	private StateMachine<States, Events> stateMachine;
		
	@Test
	public void test() throws Exception {
		stateMachine.start();
        stateMachine.sendEvent(Events.PAY);  
        stateMachine.sendEvent(Events.RECEIVE);  
	}
 
}

1.只运行启动

java 复制代码
@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        //stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        //stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}

2.运行启动与支付操作

java 复制代码
@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        //stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        //stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}

3.全部执行

java 复制代码
@Test
	public void test() throws Exception {
		stateMachine.start();    //springboot启动时开启  待支付
        stateMachine.sendEvent(Events.PAY);   //支付操作   待收货
        stateMachine.sendEvent(Events.RECEIVE);  //收货操作   结束
	}
相关推荐
v***43175 小时前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring
后端小张5 小时前
【JAVA 进阶】SpringBoot 事务深度解析:从理论到实践的完整指南
java·开发语言·spring boot·后端·spring·spring cloud·事务
ChinaRainbowSea6 小时前
13. Spring AI 的观测性
java·人工智能·后端·spring·flask·ai编程
蒂法就是我7 小时前
策略模式在spring哪里用到了?
java·spring·策略模式
后端小张9 小时前
【JAVA 进阶】Spring Cloud 微服务全栈实践:从认知到落地
java·开发语言·spring boot·spring·spring cloud·微服务·原理
李昊哲小课9 小时前
SSM框架完整教程
spring boot·spring·spring cloud
y***613115 小时前
【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目
java·spring boot·spring
黄昏恋慕黎明16 小时前
spring MVC了解
java·后端·spring·mvc
RainbowSea19 小时前
13. Spring AI 的观测性
java·spring·ai编程