快速浏览GoF和Head First Design Patterns一书,似乎没有提到Observer模式的无限循环检测和处理?
我认为如果它在两个类之间,我们可以更加小心无限循环问题,但是如果有5个类或12个类,并且观察者进行多方向怎么办?在这种情况下,是否可以进行无限循环,并且应该在此模式中添加一些检测?
答案 0 :(得分:10)
无限循环只有在以下情况下才会发生:(a)观察者也是可观察的,(b)他们观察到的变化本身会导致变化,(c)观察图是循环的,(d)有一种变化,最终可能会触发相同类型的更改。理想的解决方案是通过确保缺少其中一个要求来设计无限循环的风险。如果您当前的设计使所有四个都成立,请查看您是否可以更改它以使其中一个为假。
Observer-Observable的传统用法是在分层体系结构中 - 例如,视图控制器观察模型对象,或者事件处理程序观察GUI组件 - 这里,图形不会是循环的,所以没有无限的风险循环。
关于不同类型的变化,我应该解释一下(d)点。我的意思是,如果你有一种情况,例如,UserInputEvent可以触发ModelStateChangedEvent,而ModelStateChangedEvent可以触发WidgetUpdateEvent,它本身不能触发任何东西,那么即使观察者形成一个循环图,你也永远不会获得无限循环,因为事件序列中只有有限数量的阶段。实际上,即使观察者没有,事件也会形成一个非循环图。但是,如果ModelStateChangedEvent可以触发另一个ModelStateChangedEvent,则存在循环风险。
如果你真的无法避免周期风险,那么你可以从Jon Postel窃取一个想法,并使每个事件通知带有一个整数生存时间计数器。当一个Observable广播一个'原始'事件,意味着从观察者网络外部传来的东西并在其中启动一系列事件时,它将计数器设置为一些合适的初始TTL值。当Observable通过广播另一个事件来响应事件时,它将使用比触发事件小TTL的TTL。当Observer收到TTL为零的通知时,它会忽略它。这样可以防止无限循环,但也会阻止Observer“正确”响应某些事件,所以谨慎使用它是一个想法。我强烈建议事件级联达到TTL限制应该被认为是编程错误的结果,并且应该以与处理NullPointerException或断言失败相同的方式进行记录和报告。
答案 1 :(得分:4)
无限循环处理可能是模式实际实现的一部分,但模式本身的描述应该是通用的,而不是关注这些细节。
答案 2 :(得分:1)
没有。任何导致无限循环的情况显然都是糟糕设计的标志。我从未在观察者身上看到这种情况偶然发生,我认为没有必要在观察者中为它编写特殊情况。
这是一个不要那么做的案例。
答案 3 :(得分:1)
一般来说,无限循环检查相当于图灵的暂停问题? 如果是这样,则无法实现。
答案 4 :(得分:1)
正如@Matthew所指出的,这将是一个设计不佳的情况,你应该在设计过程中抓住它并通过改进设计来解决它,而不是增加代码的复杂性。具体来说,我认为这将表明课程缺乏凝聚力,责任通过各种课程分散,而不是适当地分配给单个班级或一小组合作班级。正确应用于良好的架构设计,Observer模式不需要任何特殊处理来防止无限生成回调。
答案 5 :(得分:1)
高评级的人给出这样一个无用的答案有点奇怪。 叹息
事件循环发生并且在GUI编程中经常发生。在我看来,或多或少的标准解决方案是通过过滤重复或冗余事件来破坏循环,或引入一些不触发事件的方法。