feat: 状态机支持发布、订阅事件.

This commit is contained in:
2025-01-24 09:43:34 +08:00
parent 54e6f56bc6
commit a1bdb96638
5 changed files with 52 additions and 5 deletions

View File

@@ -9,6 +9,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
/** /**
* 状态机抽象实现, 实现最基本功能 * 状态机抽象实现, 实现最基本功能
@@ -31,6 +32,10 @@ public abstract class AbstractStateMachine<S> extends AbstractStateManager<S> im
* 交换事件集合 * 交换事件集合
*/ */
protected final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers; protected final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers;
/**
* 事件注册集合
*/
protected final Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries;
/** /**
* 异步执行器 * 异步执行器
*/ */
@@ -55,6 +60,7 @@ public abstract class AbstractStateMachine<S> extends AbstractStateManager<S> im
Map<S, List<StateHandlerWrapper<S>>> entryHandlers, Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers, Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers, Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor, Executor executor,
Boolean async Boolean async
) { ) {
@@ -64,6 +70,7 @@ public abstract class AbstractStateMachine<S> extends AbstractStateManager<S> im
this.exchangeHandlers = exchangeHandlers; this.exchangeHandlers = exchangeHandlers;
this.executor = executor; this.executor = executor;
this.async = async; this.async = async;
this.eventRegistries = eventRegistries;
} }
@Override @Override

View File

@@ -5,6 +5,7 @@ import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Consumer;
/** /**
* 状态机的标准实现 * 状态机的标准实现
@@ -28,14 +29,18 @@ public class StandardStateMachine<S> extends AbstractStateMachine<S> implements
Map<S, List<StateHandlerWrapper<S>>> entryHandlers, Map<S, List<StateHandlerWrapper<S>>> entryHandlers,
Map<S, List<StateHandlerWrapper<S>>> leaveHandlers, Map<S, List<StateHandlerWrapper<S>>> leaveHandlers,
Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers, Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers,
Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries,
Executor executor, Executor executor,
Boolean async Boolean async
) { ) {
super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, executor, async); super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
} }
@Override @Override
public void publish(Object event) { public void publish(Object event) {
List<Consumer<StateMachine<S>>> consumers = eventRegistries.get(event);
if (consumers != null) {
consumers.forEach(consumer -> consumer.accept(this));
}
} }
} }

View File

@@ -5,6 +5,7 @@ import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper;
import java.util.*; import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Consumer;
/** /**
* 状态机构建 * 状态机构建
@@ -38,6 +39,7 @@ public final class StateMachineBuilder<S> {
private final Map<S, List<StateHandlerWrapper<S>>> entryHandlers = new HashMap<>(64); private final Map<S, List<StateHandlerWrapper<S>>> entryHandlers = new HashMap<>(64);
private final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers = new HashMap<>(64); private final Map<S, List<StateHandlerWrapper<S>>> leaveHandlers = new HashMap<>(64);
private final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers = new HashMap<>(64); private final Map<String, List<StateHandlerWrapper<S>>> exchangeHandlers = new HashMap<>(64);
private final Map<Object, List<Consumer<StateMachine<S>>>> eventRegistries = new HashMap<>(64);
private StateMachineBuilder(List<S> states) { private StateMachineBuilder(List<S> states) {
this.stateList = states; this.stateList = states;
@@ -169,6 +171,18 @@ public final class StateMachineBuilder<S> {
return whenEntry(state, handler, null); return whenEntry(state, handler, null);
} }
/**
* 注册当前状态机感兴趣的事件
*
* @param event 事件
* @param logic 切换逻辑
*/
public StateMachineBuilder<S> whenHappened(Object event, Consumer<StateMachine<S>> logic) {
List<Consumer<StateMachine<S>>> consumers = eventRegistries.computeIfAbsent(event, k -> new ArrayList<>());
consumers.add(logic);
return this;
}
/** /**
* 指定状态机的执行器 * 指定状态机的执行器
* <p> * <p>
@@ -238,7 +252,7 @@ public final class StateMachineBuilder<S> {
} }
if (type.equals(StateMachineType.STANDARD)) { if (type.equals(StateMachineType.STANDARD)) {
return (M)new StandardStateMachine<>(stateList, entryHandlers, return (M)new StandardStateMachine<>(stateList, entryHandlers,
leaveHandlers, exchangeHandlers, executor, async); leaveHandlers, exchangeHandlers, eventRegistries, executor, async);
} }
throw new IllegalArgumentException("未知的状态机类型: " + type); throw new IllegalArgumentException("未知的状态机类型: " + type);
} }

View File

@@ -2,6 +2,7 @@ package com.serliunx.statemanagement;
import com.serliunx.statemanagement.machine.StateMachine; import com.serliunx.statemanagement.machine.StateMachine;
import com.serliunx.statemanagement.machine.StateMachineBuilder; import com.serliunx.statemanagement.machine.StateMachineBuilder;
import com.serliunx.statemanagement.support.PrinterEvent;
import com.serliunx.statemanagement.support.PrinterState; import com.serliunx.statemanagement.support.PrinterState;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.Test; import org.junit.Test;
@@ -21,7 +22,7 @@ public class MachineTest {
@Test @Test
public void testStandardStateMachine() throws Exception { public void testStandardStateMachine() throws Exception {
StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.values()) StateMachine<PrinterState> stateMachine = StateMachineBuilder.from(PrinterState.values())
.async() .async(false)
.standard() .standard()
.executor(Executors.newFixedThreadPool(16)) .executor(Executors.newFixedThreadPool(16))
.whenLeave(PrinterState.IDLE, h -> { .whenLeave(PrinterState.IDLE, h -> {
@@ -33,9 +34,17 @@ public class MachineTest {
.whenEntry(PrinterState.STOPPED, h -> { .whenEntry(PrinterState.STOPPED, h -> {
System.out.println(Thread.currentThread().getName() + ": entry STOPPED, from " + h.getFrom()); System.out.println(Thread.currentThread().getName() + ": entry STOPPED, from " + h.getFrom());
}) })
.whenHappened(PrinterEvent.TURN_ON, m -> {
m.switchTo(PrinterState.SCANNING);
})
.whenHappened(PrinterEvent.TURN_OFF, m -> {
if (m.switchTo(PrinterState.STOPPING))
m.switchTo(PrinterState.STOPPED);
})
.build(); .build();
stateMachine.switchNext(false); stateMachine.publish(PrinterEvent.TURN_ON);
stateMachine.close(); stateMachine.close();
} }
} }

View File

@@ -0,0 +1,12 @@
package com.serliunx.statemanagement.support;
/**
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
* @since 2025/1/24
*/
public enum PrinterEvent {
TURN_ON,
TURN_OFF,
}