[GoF]-ConcreteSubject 可以覆盖通知方法吗?

Can a [GoF]-ConcreteSubject override the notify method?

我正在对以下情况建模:

现在我会制作一张图表,其中使用观察者模式描述每个列表实现不同类型的 notify() 的事实(例如,列表状态的某些更改只需要通知某些观察者, 有一些标准)

我做了类似的东西:

在这种情况下,每个主体都会重写通知方法,以便根据某些标准仅通知观察者的某些子集,并使用正确的更新方法。

例子

ListaMDDpubblico 是由一些文件组成的列表,每个文件都有一个特定的标签。加载文件时,仅应使用 updateMDD.

通知“喜欢”文件标签的用户关联的 notificationBox

[GoF] 友好吗?

或者我需要制作 3 个不同的 Subject 抽象 class,每个都在列表方式中实现通知方法?

提前致谢

[编辑]

经过对答案和评论的一些推理,我对这种情况的另一种可能设计是:

通过这种方式,每个更改都会通知所有订阅的观察者(对于每个不同类型的主题),并且理解是否必须考虑通知的逻辑在 notificationBox 实现的更新方法中建模(因此通知现在是广播,每个 ConcreteSubject 不需要对 concreteObserver 一无所知。

GoF 书在第 298-299 页详细解决了这个问题。我认为上面显示的设计最接近,

Specifying modifications of interest explicitly. You can improve update efficiency by extending the subject's registration interface to allow registering observers only for specific events of interest. When such an event occurs, the subject informs only those observers that have registered interest in that event.

然而,GoF 书中实现这一点的方式与上面所示的设计略有不同。上面的设计扩展了观察者接口以指定每种类型的事件,因此事件类型的知识传播到每个主题(以及每个观察者,如果有多个)。此外,如果将来添加新的事件类型,那么诱惑将是编辑观察者界面。

出于这些原因,我更喜欢使用多个观察者的方法。与其将所有更新方法合并到一个接口中,不如将它们分成 GsObserverMddObserverDdlObserver。每个主题只能注册这些观察者接口中的一个,但是 NotificationBox 可以实现所有三个。

你的观察者与 GoF 模式的比较

在GoF观察者中,notify()是在抽象Subject中实现的:调用所有观察者的update()函数,由他们决定是否通知object-update是否相关。这样,主体不必知道关于观察者的任何具体信息。

第一个潜在的设计问题

如果让 Subject 决定通知哪个 Observer,对象可能需要了解有关观察者的更多详细信息。根据主体需要了解的关于观察者的决策,这可能是也可能不是:

  • 如果具体的主体需要了解具体的观察者,这种设计会以一种不可取的方式增加耦合。事实上,这与 open/close principle 背道而驰,因为添加新类型的观察者需要调整具体的主题。维修噩梦在望!
  • 如果具体主体只需要知道抽象观察者的接口,你的设计就可以了。本着 DRY I'd nevertheless suggest to combine this pattern with the template method pattern 的精神,让 notify() 具有一般性,并使其依赖于可以根据具体主题而变化的抽象条件。

第二个潜在的设计问题

看来您的具体观察者需要知道主题的类型才能调用正确的更新函数。我不确定是否真的如此,但这是您对 updateXXX() 命名约定的印象,因为每个 XXX 仅用于一个主题。

如果是这种情况,Observer 抽象将取决于 Subject 的具体实现。这似乎不是一个好主意:具体的 classes 可能依赖于抽象的 classes,但相反是违反 open/close 原则的。

UML 建模问题

在UML图上,我建议不要使用从SubjectObserver的黑色合成菱形:

  • 复合(黑色菱形)表示观察者完全属于该主题(即如果主题被删除,其观察者将无法生存)。我怀疑这里是这种情况。
  • 聚合(白色菱形)具有相似的含义,但具有共享所有权(不是排他性)。我不能排除这一点,但我也看不到在这里使用它的令人信服的论据。
  • 我会推荐一个简单的(一对多)关联。
  • 如果您在主题一侧保留 1 的重数,您的观察者将必须在其构造期间进行注册。这是您打算实施的,还是应该是 0..1 ?

从具体观察者到所有具体主体的可导航关联提出了问题:

  • 具体的观察者和抽象的主体之间是否存在可导航的关联? (这里画出与摘要的关联class,为了准确)
  • 或者是否有 3 个可导航关联:在具体观察者和每个具体主题之间?

想想这方面的open/close原则。如果您需要添加一个新的具体主题,您希望发生什么?您是否必须更改所有具体观察者(添加新关联)?还是您希望它在没有任何变化的情况下工作(因为关联与抽象主题有关)?