观察员模式负债:为什么观察者会改变其主题?

时间:2012-04-03 12:28:42

标签: design-patterns

在阅读关于观察者模式的文章时,我遇到了在观察者模式负债下列出的下面的点

  

观察者对象是完全独立的,他们不了解观察者的存在。因此,在通知所有观察者之前, Observer对象可以更改主题的状态(在Update方法中)。这可能会导致状态不一致,状态更改通知将丢失。

  1. 为什么观察者会改变主题?不应该通过主题变化通知观察员,而不是单独改变主题吗?
  2. 如果可能的话

    1. 请让我知道thro'一个例子
    2. 同时说明为什么主题不能限制自己允许任何观察者在通知所有观察者之前更改它?

3 个答案:

答案 0 :(得分:3)

没有任何地方声明观察者本身不能改变其主题,尽管由于上述原因,在大多数情况下不建议使用观察者。但是,从技术上讲,这是可能的,特别是如果通知调用包含主题本身作为参数:

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

至于如何防止观察者在通知周期进行时改变主题,我看到了一些选项,但是每一个都引入了额外的复杂性,这些都不是100%保证,有些比它的价值更麻烦

  • 只传递Subject对观察者的只读界面 - 这是最容易实现的,没有任何副作用,但是邪恶的观察者仍然可能尝试向下转换主题以访问其修饰符方法,和/或访问完整主题通过其他一些对象
  • 将公共主题实现为真实主题的只读适配器,并仅发布前者 - 这可以防止向下转换技巧,并且可能使观察者更难(但不是不可能)通过某些访问真正的主题其他对象
  • 通过设置,例如“锁定”主题的更新时间一个标志,在每个修改器方法中检查(然后例如,如果标志打开则抛出异常) - 这不仅可以防止观察者,而且可以防止每个人在关键时刻修改主题,这可能是也可能不是。

答案 1 :(得分:1)

虽然不推荐,但没有什么能阻止观察者改变观察对象的状态(通常,参见C ++中的const-correctness以反例)。当然,观察到的物体可能会跳过箍以防止/不允许这样做,但这很乏味。

如果在所有其他观察者访问该对象之前状态发生了变化,他们会发现一个与他们期望的状态不同的状态(被通知)。

答案 2 :(得分:1)

如果我们的主题是S,我们有两名观察员注册; AB,然后:

如果A的{​​{1}}包含可修改responseHandler()的代码,则会在S收到通知之前更改S的状态。

处理特定排序或其他特殊条件的代码属于B的{​​{1}}方法,您可以将S标记为不可修改或准备某些特定的通知顺序更新notifyObservers()