【问题标题】:State pattern and guard状态模式和守卫
【发布时间】:2015-07-01 07:49:16
【问题描述】:

更新:

状态模式可能是解决此问题的错误方法。因此,欢迎任何其他模式。基本上,我正在寻找一种方法来为每个状态设置保护条件,同时拥有干净且可维护的代码。 emberjs、ui-router、react-router等前端路由系统如何实现guard conditions,避免条件不满足时进入特定状态?


我想通过使用状态模式来实现一个有限状态机,但我无法理解它。简而言之就是:

If error -> error state
If A && B && C -> second state
If only A -> first state

在任何状态下,一旦发生错误,我们就会进入错误状态。输入(事件)A、B 和 C 可能以任何顺序到达,但如果它们都通过,我们将进入第二状态。如果只有输入 A 适用,那么我们进入第一个状态。

以下状态图取自 Martin Fowler 的领域特定语言一书。

在描述中他说:

格兰特小姐,在她的卧室里有一个秘密隔间 这通常是锁定和隐藏的。要打开它,她必须关闭 门,然后打开她胸前的第二个抽屉,转动她 按任意顺序打开床头灯。搞定这些秘密 面板已解锁,她可以打开。

我强调,turning lightopening 2nd drawer 可以按任意顺序发生。同A、B、C。

根据@SQLPolice 的评论和书,我画了这个:

但问题是,我可能有 (A && B && C && D && D && E)。在那种情况下,拥有所有的组合临时状态会很麻烦。

【问题讨论】:

  • 我假设你有一个开始状态?
  • 你在画什么... UML/Flow...?
  • @DavidBarker,两者都不是。我只需要一些直观的东西来理解如何实现。
  • 好的,但是当你只有A时,你想进入不同的状态。但是,如果您将 A 作为第一个事件会发生什么?你怎么知道 B 或 C 会跟随?
  • 哦,现在画得真好! - 是的,你是对的,当变得更复杂时它会变得非常非常麻烦。这就是您使用工具创建此类状态机的原因——例如lexflex 等(用于词法分析)。他们创建带有大量标签的 C 代码,goto 跳转...

标签: design-patterns state-machine state-pattern state-diagram


【解决方案1】:

您可以为此使用某种形式的词法分析。我会通过限制从一个状态转换的能力来解决这个问题,除非满足两个状态之间的边缘上的约束。我最近用 PHP 为 Laravel 框架编写了一个 FSM,其中有一个示例,例如,在发生转换之前,各种约束都必须为真。它使用状态中的伪状态或句柄来切换表示进程已完成的标志。只有当所有标志都设置为true时,才能进行状态转换。

使用我为 laravel 编写的 FSM 包,一个示例 FSM 设置 would look something like this

每个状态都会(onEnter)或通过伪状态将其在 FSM OR State 上的约束标志设置为 true。

这也会触发checkReady(),它会根据约束标志触发转换或保持当前状态。

添加新约束是将它们添加到状态或包含 FSM 内的约束数组中,并构建一个方法以允许在执行任务时删除约束。

当您查看多个状态时,每个状态都形成对约束的要求。 A sample state would look something like this.

当您查看具有伪状态/处理程序的单个状态时。 The state would look something like this, where it's logic is contained.

【讨论】:

    【解决方案2】:

    草稿如下:

    【讨论】:

    • 谢谢,但我如何避免写if (A && B && C)?原因是,我已经有很多条件不同的 if 和 else。选择状态机的唯一原因是避免这样做。
    • 啊,我明白了。这背后是什么 - 这是学校的家庭作业,还是您想实现什么?
    • 这不是作业。我比这种东西还老。这是我们遇到的真正问题,我们正在努力简化事情。
    • 这是不久前的事了,但我大致记得这是如何通过词法分析完成的。您可以使用一系列 临时状态 来解散“A & B & C”,如下所示:如果您有 A,则切换到临时状态 1。现在,如果您有 B,然后进入中间状态 2,但如果没有,则进入最终状态 1。在中间状态 1 中,如果你有 C,则进入最终状态 2。这是一种可能的方式,就像自动化工具一样。跨度>
    • 制作一个过渡事件D where D = (A && B && C)?
    【解决方案3】:

    状态机抽象包括:

    1. 国家
    2. 事件或输入
    3. 过渡
    4. 操作

    像 a&&b&&c 这样的语句实际上是一个事件或输入……一个转换的标签。因此,如果您要适应状态机抽象,则需要将其映射到事件。您需要编写代码来进行映射。

    如果您的状态机通常由此类条件驱动,您需要挂钩 a b 和 c 发生变化的事件,或者在计时器上定期检查它们。每当它们发生变化时,您的代码都会映射到一个事件并将它们发布到任何推进状态机的代码中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      • 2015-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      相关资源
      最近更新 更多