观察者模式:避免不良的重入行为?

wil*_*ick 5 design-patterns

在实践中,Observer模式的实现如何避免由于重入而导致的不良行为?

为了澄清"不良行为",请考虑模式中的Subject在单线程同步实现中具有方法MethodA()和MethodB(),事件OnMethodA()和OnMethodB()以及一个或多个Observers的情况:

  • 调用Subject.MethodA(),
  • Subject对MethodA()做了什么,然后为所有Observers调用OnMethodA(),
  • Observer1获取OnMethodA()事件,并调用Subject.MethodB(),
  • 主题执行它对MethodB()所做的操作,然后为所有观察者调用OnMethodB(),

此时,我们正在为所有观察者调用OnMethodB(),即使我们仍处于OnMethodA()通知的中间.这意味着列表中Observer1之后的任何观察者都会在"OnMethodA()"之前看到"OnMethodB()" - 这是不好的行为.

  • Observer2(由对Observer1一无所知的开发人员编写)获取OnMethodB()事件,并调用Subject.MethodA(),
  • …永远.Subject.MethodA() - > Observer.OnMethodA() - > Subject.MethodB() - > Observer.OnMethodB() - > Subject.MethodA() - > etc ...

现在你要溢出堆栈.这是不好的行为.

如果您从一开始就设计了基于队列的异步通知,或者在通知期间对Subject调用抛出异常,则可以避免这种情况,并且这很容易理解.困扰我的是我几乎从来没有把这提到作为实现模式的最佳(或真正的,唯一的)实践.你必须已经意识到谷歌"观察者模式可重入"的问题,并且搜索中的结果似乎只是遇到问题的人,而不是关于模式的书中的警告.

我错过了什么吗? 在实践中,Observer模式的实现如何避免由于重入而导致的不良行为?

Ibr*_*jar 0

嗯,我以前从未听说过 Observable 模式的这个问题,所以+1。另一方面,为什么不看看 Java 如何通过ObserverObservable在java.util 包中实现此模式,另一个注意事项是,由于此模式使用不当,在现实世界的应用程序中会出现此问题,请查看Martin Fowler 关于观察者模式的这些陷阱。