状态机笔记

文章目录

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

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

什么是状态机

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);  //收货操作   结束
	}
相关推荐
郝学胜-神的一滴23 分钟前
超越Spring的Summer(一): PackageScanner 类实现原理详解
java·服务器·开发语言·后端·spring·软件构建
MX_935913 小时前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
程序员泠零澪回家种桔子14 小时前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构
晚霞的不甘16 小时前
CANN 编译器深度解析:UB、L1 与 Global Memory 的协同调度机制
java·后端·spring·架构·音视频
寄存器漫游者17 小时前
Linux 软件编程 - IO 编程
linux·运维·spring
我真会写代码17 小时前
SSM(指南一)---Maven项目管理从入门到精通|高质量实操指南
java·spring·tomcat·maven·ssm
vx_Biye_Design17 小时前
【关注可免费领取源码】房屋出租系统的设计与实现--毕设附源码40805
java·spring boot·spring·spring cloud·servlet·eclipse·课程设计
独断万古他化20 小时前
【SSM开发实战:博客系统】(三)核心业务功能开发与安全加密实现
spring boot·spring·mybatis·博客系统·加密
若鱼191921 小时前
SpringBoot4.0新特性-Observability让生产环境更易于观测
java·spring
跳动的梦想家h21 小时前
环境配置 + AI 提效双管齐下
java·vue.js·spring