我读过的关于观察者设计模式的参考文献(GOF设计模式,头部设计模式,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
界面中将其作为字段?
最终,鉴于模式本身似乎放松了主体与其观察者的耦合,为什么在将观察者与其主体耦合时,这似乎不会得到提升?
或者是吗?我只是基于我读过的例子。
答案 0 :(得分:6)
从您的图片中,您的“更新()”方法没有收到有关主题状态的任何信息,因此,如果观察者需要有关此状态的信息(通常在观察者模式中) ),然后它必须从ConcreteSubject 中检索它,调用“GetState()”方法(不存在于ISubject中)。
此模式的替代方法是将状态(或对整个ConcreteSubject的引用)作为“update()”方法的参数传递。
对引用ConcreteSubject而不是ISubject 的其他一般性解释可能是您可能希望与ConcreteSubject交互以调用业务逻辑(当然不会在ISubject接口中公开)。
答案 1 :(得分:2)
仅仅因为您阅读的定义subject holds a reference to the concrete observer
并不意味着您必须从字面上理解它。
只要主题具有对观察者的引用/链接,无论是具体的还是通过接口/类,该语句都是正确的。
在IObserver和IObservable两侧都可以看到一个接口。我认为你要发现的问题是,当你制作主题摘要时,你真的必须努力寻找如何来使你的状态变得通用。
答案 2 :(得分:1)
具体观察者,具体主题实施也有状态。当主题的状态发生变化时,具体观察者的状态也在更新。但有时候,你可能需要看到你没有的主题状态,为此,你最好参考主题。换句话说,为了看到具体主体的状态。
答案 3 :(得分:1)
我会尽力提供自己的观点。
为什么具体?它们会不会导致主题和观察者之间的耦合?
观察者模式的主要关注点是1-to-N模型,而不是N-to-N,这是通过Observer界面实现的。
是的,它会导致耦合并达到预期的目的,因此每个具体的观察者都将获得所需的内容,而无需多余的“上下文传递”。
耦合不好,但原理>去耦合。
如果通过“主题”界面访问具体主题,我们可以在运行时订阅其他主题!对吧?
update()
,它只能做一件事。 单一责任原则。update()
中。一些书籍/在线资源作者将update()
变成类似update(subject, context, varName, ...)
的东西,然后他们假设观察者将需要什么,但是
观察者所需要的与主题无关,为什么不自己考虑呢?
将ConcreteObserver耦合到ConcreteSubject,以便主题的工作只是发送通知,而不是数据。
主题:嘿,我的商店所有人都开门了!
旁观者A:好的,我想我需要那部iPhone。
ObserverB:好的,我想我需要那台Windows计算机。
观察员C:我同时喜欢iPhone和Windows计算机,也许我应该问A,B这个消息。