【问题标题】:Observer pattern liabilities: Why would observer change its subject?观察者模式责任:为什么观察者会改变它的主题?
【发布时间】:2012-04-03 12:28:41
【问题描述】:

在阅读有关观察者模式的文章时,我在观察者模式的责任下遇到了以下几点

Observer 对象是完全独立的,它们不知道其他 Observers 的存在。因此,Observer 对象可以在通知所有 Observer 之前更改 Subject 的状态(在 Update 方法中)。这可能会导致状态不一致,并且状态更改通知将会丢失。

  1. 为什么观察者会改变主题?不是应该通知观察者更改主题而不是自行更改主题吗?

如果可以的话

  1. 请通过示例告诉我
  2. 还要说明为什么主体不能限制自己允许任何观察者在更早的更改通知所有观察者之前对其进行更改?

【问题讨论】:

    标签: design-patterns


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

      虽然不建议这样做,但没有什么可以阻止观察者改变被观察对象的状态(通常,参见 C++ 中的 const-correctness 作为反例)。当然,被观察的物体可能会跳过箍来防止/禁止这种情况,但这很乏味。

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

      【讨论】:

        【解决方案3】:

        如果我们的主题是S,并且我们注册了两个观察者; AB,然后:

        如果AresponseHandler() 包含修改S 的代码,那么它会在B 收到通知之前更改S 的状态。

        处理特定顺序或其他特殊条件的代码将属于SnotifyObservers() 方法,您可以在其中将S 标记为不可修改,或者准备一些特定的通知顺序以更新S

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-25
          • 1970-01-01
          • 1970-01-01
          • 2016-02-20
          • 2023-04-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多