【问题标题】:Observer Design Pattern - Concrete Subjects and Observers观察者设计模式 - 具体的主题和观察者
【发布时间】:2011-09-25 05:56:38
【问题描述】:

我读过的关于观察者设计模式的参考资料(GOF 设计模式、Head First Design Patterns、http://www.dofactory.com/Patterns/PatternObserver.aspx)规定具体的主题持有对具体观察者的引用。很像这样:

class ConcreteObserver : IObserver
{
    ConcreteSubject concreteSubjectInstance;
    //other code, etc.
} 

现在,如果具体的 Subject 本身实现了一个 Subject 接口(或派生自某个抽象 Subject 类),为什么不让 ConcreteObserver 中的类型成为那个抽象/接口呢?即

class ConcreteObserver : IObserver
{
    ISubject concreteSubjectInstance;
    //other code, etc.
} 

此外,为什么不直接将其设为(例如)IObserver 接口中的字段?

最终,鉴于模式本身似乎放松了 Subject 与其 Observers 的耦合,为什么在将 Observer 与其主题耦合时似乎没有得到提升?

是吗?我只是基于我读过的例子。

【问题讨论】:

    标签: design-patterns observer-pattern


    【解决方案1】:

    同意@Rainning,具体的观察者可能对 Observable 的不同领域感兴趣。 观察者可以在自己的更新方法中得到他想要的。 这是我用c++学习《head first design pattern》的一个例子:

    https://github.com/jwbecalm/Head-First-Design-Patterns-in-CPP/tree/main/ch02_Observer

    还包括植物类

    【讨论】:

      【解决方案2】:

      我会尽量提供我的观点。

      为什么是混凝土?它们不会导致 Subject 和 Observer 之间的耦合吗?

      • 观察者模式主要关注的是1-to-N模型,而不是N-to-N,这是通过观察者接口实现的。

      • 是的,它会导致耦合,这是有意为之的,因此每个具体的观察者都会得到他想要的,而没有多余的“上下文传递”。

      耦合不好,但原理>解耦。

      如果通过Subject接口访问一个具体的Subject,我们可以在运行时订阅不同的Subject!对吧?

      • 不,对于每个具体观察者的update(),它应该只做一件事单一职责原则
      • 如果想收听许多事件怎么办?这可以通过 Composition 来完成,而不是将所有内容集中在一个 update() 中。

      一些书籍/在线资源作者将update() 变成update(subject, context, varName, ...) 之类的东西,然后他们假设观察者需要什么,但是

      观察者需要的不是主体所关心的,为什么不自己考虑呢?

      将 ConcreteObserver 与 ConcreteSubject 耦合,因此 Subject 的工作只是发送通知,而不是发送数据。

      主题:大家好,我的店开张了!
      ObserverA:好的,我想我需要那部 iPhone。
      ObserverB:好的,我想我需要那台 Windows 电脑。
      ObserverC:我喜欢iPhone和Windows电脑,也许我应该向A,B询问消息。

      【讨论】:

        【解决方案3】:

        具体的观察者和具体的主题实现也有状态。当主体的状态发生变化时,具体观察者的状态也在更新。但有时,您可能需要查看您没有的主题状态,为此,您最好参考主题。也就是说,为了看到具体主体的状态。

        【讨论】:

          【解决方案4】:

          从您的图片来看,您的“update()”方法不会收到任何有关主题状态的信息,因此,如果观察者需要有关此状态的信息(与观察者模式中的往常一样) ),然后它必须从调用“GetState()”方法(ISubject 中不存在)的 ConcreteSubject 中检索它。

          此模式的替代方案是将状态(或对整个 ConcreteSubject 的引用)作为“update()”方法的参数传递。

          引用 ConcreteSubject 而不是 ISubject 的其他一般解释可能是您可能希望与 ConcreteSubject 交互以调用业务逻辑(当然不会在 ISubject 接口中公开)。 p>

          【讨论】:

          • '作为参数传递给更新方法':我猜它也可以作为观察者构造函数的参数。
          • 是的,要设置内部引用,它应该在构造函数中完成。但是,如果您不维护内部引用,您仍然可以在每个“update()”调用中收到。这就是 Java 内置的观察者模式实现的工作方式。
          【解决方案5】:

          仅仅因为您阅读的定义声明subject holds a reference to the concrete observer 并不意味着您必须逐字阅读。

          只要主体具有对观察者的引用/链接,无论是具体的还是通过接口/类,该陈述仍然正确。

          在 IObserver 和 IObservable 两边都看到一个接口是很常见的。我认为您将要发现的问题是,当您将主题抽象化时,您真的必须努力并找到 如何 使您的状态具有通用性。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-24
            • 1970-01-01
            • 2011-11-25
            • 2019-08-22
            • 2016-02-20
            相关资源
            最近更新 更多