实际上,观察者模式的实现如何避免由于重入导致的不良行为?观察者模式:避免不良的重入行为?
为了阐明“不良行为”,考虑模式中的Subject有单线程方法MethodA()和MethodB(),事件OnMethodA()和OnMethodB()以及一个或多个Observers的情况同步实现:
- Subject.MethodA()被调用,
- 主题做什么它为methodA(),然后调用OnMethodA()为所有的观察员,
- Observer1得到OnMethodA( )事件,并调用Subject.MethodB(),
- 该主题做什么它的方法b(),那么对于所有的观察员呼吁OnMethodB(),
在这一点上,我们称之为OnMethodB()所有观察员,尽管我们仍然在通知中的中间为OnMethodA()。这意味着列表中的Observer1之后的任何观察者都将在“OnMethodA()”之前看到“OnMethodB()” - 这是不好的行为。
- Observer2(由谁不知道什么Observer1一个开发者编写)得到OnMethodB()事件,并调用Subject.MethodA(),
- ...永远。 Subject.MethodA() - > Observer.OnMethodA() - > Subject.MethodB() - > Observer.OnMethodB() - > Subject.MethodA() - >等...
现在你要溢出堆栈。那是不好的行为。
如果你已经设计了异步,基于队列的通知,从一开始,或通知期间抛出的通话主题的例外,就可以避免这一点,这是很容易理解。有什么困扰我的是,我几乎从来没有把这种做法看作是实施该模式的最佳(或者真的,唯一的)做法。你必须已经意识到谷歌“观察者模式可重入”的问题,并且搜索结果似乎只是遇到问题的人,而不是关于模式的书中的警告。
所以我错过了什么? 在实践中,Observer模式的实现如何避免由于重入导致的不良行为?