观察者模式的责任:为什么观察者会改变它的主题?

4
当阅读观察者模式的文章时,我发现在观察者模式的责任中列出了以下观点:
观察者对象是完全独立的,它们不知道其他观察者的存在。因此,在通知所有观察者之前,观察者对象可以更改主题的状态(在更新方法中)。这可能导致状态不一致,并且状态更改通知将丢失。
1.为什么观察者会更改主题?难道观察者不应该在主题发生变化时被通知,而不是自行更改主题吗?
2.如果可能,请通过一个例子让我知道具体情况,同时请指明为什么主题不能限制任何观察者在通知所有观察者之前更改主题?
3个回答

3

并没有明确规定观察者不能改变其主题,尽管在大多数情况下不建议这样做,原因如上所述。但从技术角度来看,这是可能的,特别是如果通知调用包括主题本身作为参数:

class MyObserver implements Observer<MySubject> {
  ...
  public void notify(MySubject theSubject) {
    ...
    theSubject.changeSomeProperty(newValue);
  }
  ...
}

关于如何防止在通知循环期间观察者修改主题,我看到了一些选项,但每个选项都会引入额外的复杂性,没有一个是百分之百的保证,有些还不值得麻烦。

  • 向观察者传递Subject的只读接口 - 这是最容易实现的,没有副作用,但是一个邪恶的Observer仍然可能尝试将Subject下转型以访问其修改方法,并/或通过其他对象访问完整的Subject
  • 将公共Subject实现为真正Subject的只读Adapter,并仅发布前者 - 这可以防止下转型技巧,并且可能使观察者更难(但并非不可能)通过其他对象访问真正的Subject
  • 通过设置标志"锁定"Subject来更新时间(如果标志开启,则在每个修改器方法中进行检查,并抛出异常),这样不仅可以防止观察者而且防止任何人在关键时间修改Subject,这可能是需要的或不需要的

1

虽然不建议这样做,但观察者可以改变被观察对象的状态(通常情况下,在C++中看到const-correctness作为反例)。当然,被观察对象可能会通过各种方式防止/禁止这种情况发生,但这很繁琐。

如果在所有其他观察者访问对象之前更改了状态,则它们将发现与他们预期的(被通知的)状态不同的状态。


1
如果我们的主题是S,并且我们注册了两个观察者:AB,那么:
如果AresponseHandler()包含会修改S的代码,则在B被通知之前,它将更改S的状态。
处理特定顺序或其他特殊条件的代码应该放在SnotifyObservers()方法中,在那里您可以将S标记为不可修改,或者准备一些特定的通知顺序来更新S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接