【问题标题】:should the Observer Pattern include some infinite loop detection?观察者模式应该包括一些无限循环检测吗?
【发布时间】:2009-10-02 01:31:01
【问题描述】:

快速浏览 GoF 和 Head First Design Patterns 这本书,似乎没有提到观察者模式的无限循环检测和处理?

我觉得如果是在2个类之间,我们可以更加小心死循环的问题,但是如果有5个类或者12个类,观察者是多方向的怎么办。在这种情况下,会不会出现无限循环,应该在这个模式中添加一些检测?

【问题讨论】:

  • Arrr,Head First Design Patterns。在封面图片最愚蠢的书籍列表中名列前茅。

标签: design-patterns


【解决方案1】:

只有在以下情况下才会发生无限循环:(a) 观察者也是可观察的,(b) 他们观察到的变化会导致自身发生变化,(c) 观察图是循环的,并且 (d) 存在一种变化最终可能会触发相同类型的更改。理想的解决方案是通过确保不存在这些要求之一来设计出无限循环的风险。如果您当前的设计使所有四个都为真,请查看是否可以更改它以使其中之一为假。

Observer-Observable 的传统用途是分层架构 - 例如,视图控制器观察模型对象,或事件处理程序观察 GUI 组件 - 在这里,图形不会是循环的,因此不存在无限风险循环。

我可能应该解释一下 (d) 点,关于不同种类的变化。我的意思是,如果您遇到这样的情况,例如,UserInputEvent 可以触发 ModelStateChangedEvent,而 ModelStateChangedEvent 可以触发 WidgetUpdateEvent,它本身不能触发任何东西,那么即使观察者形成循环图,您也永远无法获得无限循环,因为事件序列中只有有限数量的阶段。实际上,事件形成了一个无环图,即使观察者没有。但是,如果一个 ModelStateChangedEvent 可以触发另一个 ModelStateChangedEvent,那么您就有循环的风险。

如果你真的无法避免循环的风险,那么你可以从Jon Postel 那里窃取一个想法,并让每个事件通知都带有一个整数生存时间计数器。当 Observable 广播一个“原始”事件时,即从观察者网络外部进入并在其中启动一系列事件的事件,它会将计数器设置为某个合适的初始 TTL 值。当一个 Observable 通过广播另一个事件来响应一个事件时,它会使用比触发事件少一个的 TTL。当观察者收到一个 TTL 为零的通知时,它会忽略它。这将防止无限循环,但也会阻止观察者“正确”响应某些事件,因此应谨慎使用。我强烈建议将达到 TTL 限制的事件级联视为编程错误的结果,并且应该以与处理 NullPointerException 或断言失败之类的事情相同的方式记录和报告。

【讨论】:

    【解决方案2】:

    无限循环处理可能是模式实际实现的一部分,但模式本身的描述应该是一般性的,而不是关心这些细节。

    【讨论】:

      【解决方案3】:

      一般来说,无限循环检查是否等同于图灵的停止问题? 如果是这样,那是不可能的。

      【讨论】:

      • 我不认为它们是等价的。假设您可以为原始事件生成一个 id。每次特定观察者看到事件时,在全局表中进行标记。如果观察者已经看到了一个事件,它就不会传播它。最终,所有注册事件的观察者都会看到它。这些都不会再次传播它,因此不会有无限循环。我不认为我刚刚解决了停机问题,但我确实认为它可以解决这个问题。
      • 比这更微妙。观察者不会重新广播他们的 Observable 中的变化;相反,观察到的变化可能会触发观察者的变化,然后需要广播。如果 A 的变化触发 B 的变化,那么 B 的变化与 A 的变化是截然不同的变化,您不能将它们组合在一个 ID 下而忽略一个。
      【解决方案4】:

      正如@Matthew 指出的那样,这将是一个糟糕的设计案例,您应该在设计过程中发现并通过改进设计来解决它,而不是增加代码的复杂性。具体来说,我认为这表明类缺乏凝聚力,责任分散在各个类中,而不是适当地分配给单个类或一小组协作类。正确应用到良好的架构设计中,观察者模式应该不需要任何特殊处理来防止无限生成回调。

      【讨论】:

        【解决方案5】:

        评分高的人给出如此无用的答案有点奇怪。 叹息

        事件循环在 GUI 编程中经常发生。在我看来,或多或少的标准解决方案是通过过滤重复或冗余事件或引入一些不触发事件的方法来打破循环。

        【讨论】:

          【解决方案6】:

          没有。任何导致无限循环的情况显然都是糟糕设计的标志。我从来没有在观察者身上看到过这种偶然发生的情况,而且我认为没有必要在可观察者中为它编写特殊情况。

          这是一个不要那样做的例子。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-02-20
            • 2023-04-10
            • 1970-01-01
            相关资源
            最近更新 更多