我有一个事件驱动架构,其中A正在等待B的变化,B正在等待C的变化,C正在等待A的变化,形成一个循环。
现在,如果B发生变化,那么A会向C发射一个事件,该事件将激活到B,然后激活到A,激活到C ... ad无限。
我现在可以改变我的程序,不包含这个循环,但是我担心我可能会在以后不能进入某个角落。在设计基于事件的系统时,如何防止这些事情发生?
答案 0 :(得分:3)
映射您的依赖项。应该没有周期。循环依赖是重新组织代码的一个很好的借口。
如果您需要其他原因试图避免死锁,它们也可能导致死锁。
答案 1 :(得分:2)
这里的每个人似乎都说循环依赖很糟糕。这在某种意义上是正确的,我试图以几乎所有成本避免静态循环依赖。您可以通过此博客中概述的控制反转来执行此操作:http://blog.schauderhaft.de/2011/07/17/breaking-dependency-cylces/
但是你所描述的并不是静态循环依赖,而是在运行时。我不完全确定,但我认为在运行时避免循环依赖或多或少是不可能的。但当然这不应该导致无限循环。为了解决这些问题,我看到了两个半选项
首先是黑客
确保由另一个事件触发的每个事件都引用了原始事件(或者像id那样的基本信息)。当你处理一个事件时,确保它不是来自你自己。
亲:易于实施;绝对防止递归
黑客的另一半
如果您正在运行同步,则可以在之前设置标记firingEvent
并在之后重置它。忽略在设置firingEvent
时进入的事件。
亲:更容易实施;在单个线程中运行时绝对可以防止递归
语义丰富的解决方案
我确信A触发某些外部触发事件以及A触发因C触发的事件实际上是两个不同的事件,或者所有三个事件实际上只是一个可能来自尚未确定的来源的事件D.或类似的东西。如果没有关于A,B和C的信息以及它们正在发射的事件,就没有办法说明。如果找到正确的事件,循环将消失。
Pro:设计更清晰,包含更多信息。
答案 2 :(得分:2)
在设计基于事件的系统时,如何防止这些事情发生?
仅在对象状态确实发生变化时才提升事件。
在引发事件时禁止更改对象状态。
答案 3 :(得分:0)
我认为这是一个很好的问题。不幸的是,我自己没有完整的答案,但这篇文章有几点好处:
how to avoid infinite loop in observer pattern?
我不认为答案是避免循环依赖,正如其他人所建议的那样。 (嗯,这取决于你对“循环依赖”的定义。)像Java这样的语言将使用接口在编译时最小化类型的循环依赖性,这通常是个好主意。例如,MVC模式中的视图类不依赖于您的应用程序,它只知道具有ValueChangedListener
,ClickListener
等名称的接口。但这并不能消除运行时对象之间的循环连接,这可能导致事件循环。
如其他链接帖子中所述,某些循环在UI工具包中停止,因为如果控制器或模型将视图的值“设置”为等于其当前值的值,则视图不会触发“已更改”事件。但在其他情况下,就像创建更复杂数据的自定义视图一样,计算当前数据和新数据的相等性是不可行的。
答案 4 :(得分:-2)
循环依赖非常糟糕。我不得不用A,B和C来写下你的帖子,然后才对我有意义。我想你应该摆脱它。如果你把自己置于一个角落,它可能比你可以遇到的循环依赖性问题好很多。
你也可以避免这种情况。 A,B和C真正紧密耦合。我想你需要重新考虑他们的责任。也许有一个共同的D元素会消耗很多你的设计压力。
我想到的其他事情是architectural Layering。如果您可以将A层叠在B上,并且需要与B对话的任何人进行通信,那么您可以给自己一个更轻松的时间。同样,我对你的问题了解不多,所以这些只是广泛的建议。
最后一个选项,也是我最不喜欢的选择,是在三个组件中的每一个之间传递消息。在访问每个组件时,要求每个组件添加它已看到消息的消息。然后,获取消息的下一个组件包含有关谁看到它的信息。有点像报名表。但同样,最不喜欢。先尝试别的。
祝你好运!