feat: 状态机支持发布、订阅事件.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user