需要两个事件进行转换的状态机最佳实践(boost::ext SML)

问题描述 投票:0回答:1

我正在尝试使用 SML 实现状态机,并且我有一个关于特定场景的最佳实践的问题。

假设状态机代表一个可以根据用户输入打开和关闭的门,但只有在安全时才关闭(用户不在门附近)。

因此,为了关闭门,我需要有一个用户命令来关闭,并且用户清除门。

后者(门清除)对我来说似乎是一个事件,但后来我遇到了一个问题,我正在尝试实现从

open
closing
的状态转换,需要两个事件(
close
userClear
)。我不知道这两个事件会以什么顺序发生,
userClear
甚至可能在进入状态
open
之前发生,或者永远不会触发,因为用户从来没有离大门太近。

在 SML 示例中,我发现可以推迟事件。也许这有点用处?

我还可以将清除状态编码为状态。这将增加我拥有的状态数量,从而产生一个像

这样的转换表
openNotClear        + clear = openClear,
openClear           + close = closingClear,
openNotClear        + close = openWaitingForClear,
openWaitingForClear + close = closingClear,
...

这似乎并不理想,因为状态空间很快就会变得很大。

我确信这种情况并不少见,并且有一个标准方法来处理此类多个事件/条件。

在事件驱动的状态机中如何最好地处理这个问题?

state-machine boost-sml
1个回答
0
投票

如果您使用的框架允许,建议使用并行状态。

此外,在这个答案中,我将考虑这样一个事实:当您的

close
事件被触发时,门应该尽可能关闭,而不需要任何其他
close
事件。 因此,除了门有两种以上的状态之外别无选择:

Gate State Machine
Closed         + open      = Opened
Opened         + close     = AboutToClose
AboutToClose   + userClear = Closed

现在,让我们想象一些并行状态(或并行运行的第二个状态机)代表大门周围的业务,具体取决于玩家的接近度:

Proximity State Machine
Clear  + userComing   = Busy
Busy   + userLeaving  = Clear

现在,您需要添加两个额外的检查才能最终实现:

  1. 当进入 Gate 状态机的“AboutToClose”状态时,验证 Proximity 状态机的状态。如果是“Clear”,则生成“userClear”事件,然后转换到“Closed”状态。
  2. 当进入 Proximity 状态机的“Clear”状态时,生成“userClear”事件。

这看起来像这样:

func1: onAboutToCloseEntered:
  if (proximity.state == Clear)
    generateEvent(userClear)

func2: onClearEntered:
  generateEvent(userClear)

如果进入 Gate 状态机的“AboutToClose”状态时,Proximity 状态机的状态为

Busy
,则不执行任何操作 (
func1
)。门状态机将保持在
AboutToClose
状态。稍后,当用户离开大门时,将生成事件
userClear
(
func2
)。

如果在

AboutToClose
状态下需要再次打开门,则只需添加一个新的转换到
Opened
状态即可。

© www.soinside.com 2019 - 2024. All rights reserved.