让我们说我们有3个状态S1,S3,S3和一个错误状态E1。 S *状态具有分别执行A1,A2,A3的动作。如果A1,A2,A3中的任何一个导致引发异常,则状态机应转到E1。有没有一种方法可以定义一个通用的过渡,即如果有任何动作引发异常,请转到E1?还是我必须明确说明每种状态的转变
states.withStates()
.initial(START)
.end(END)
.end(ERROR)
.state(S1, A1())
.state(S2, A2())
.state(S3, A3())
//Is this the only way of defining error transition? Can I dry it up?
transitions
.withExternal()
.source(S1)
.event(ErrorEvent)
.target(E1)
.and()
.withExternal()
.source(S2)
.event(ErrorEvent)
.target(E1)
.and()
.withExternal()
.source(S3)
.event(ErrorEvent)
.target(E1)
我希望能以某种方式将其干燥。如果我有10个州,那么以这种方式进行操作将变得非常重复。
答案 0 :(得分:0)
目前没有使用“状态机”构建器执行此操作的常用方法。 根据定义,每个状态转换都应在配置中明确定义。
讨论这是否是SM世界中的正确方法是另一个问题:
如果A1,A2,A3中的任何一个导致抛出异常,则状态为 机器应该转到E1。
SM应该进入错误状态还是应保持相同状态或恢复为先前状态,等等,这值得商bat。 我的理解是,当错误在任何其他状态下发生时,要转换为常见的错误状态并不是一个好方法。
这实际上取决于您需要如何处理该错误。 例如,如果要发信号通知调用代码或将错误传播到stateMachine之外,则可以为此使用StateContext或SM ExtendedContext。 您可以插入自定义标志(例如“ hasError”)和Exception本身,并将其公开给调用者代码,但这不是很优雅。有人应该在每次调用时检查该标志的存在并通知调用者代码(或者调用者代码本身应进行检查,这很丑陋)。
另一种方法是清除stateContext并保持相同状态,等待一些重试逻辑加入。 或者在您的errorAction中,您可以将ErrorEvent发送到您的SM并传递SM上下文中所需的任何信息,我相信这是您选择的方法。
无论哪种方式-所有转换都应出现在StateMachineModel
中。
该模型可以使用构建器方法创建,也可以通过编程方式创建(例如,在所有现有状态之间进行迭代比较容易,并且只需定义1个额外的过渡到错误状态即可)。
@Override
public StateMachineModel<String, String> build() {
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
Collection<StateData<String, String>> stateData = new ArrayList<>();
stateData.add(new StateData<String, String>("S1", true));
stateData.add(new StateData<String, String>("S2"));
stateData.add(new StateData<String, String>("S3"));
stateData.add(new StateData<String, String>("ERROR_STATE"));
StatesData<String, String> statesData = new StatesData<>(stateData);
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
stateData.forEach(state -> {
if (state.getState() != ERROR_STATE) {
transitionData.add(new TransitionData<String, String>(state.getState(), "ERROR_STATE", "ERROR_EVENT"));
}
});
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<String, String>(configurationData,
statesData, transitionsData);
return stateMachineModel;
}