Observer Design Pattern - Concrete Subjects and Observers
The references (GOF Design Patterns, Head First Design Patterns, http://www.dofactory.com/Patterns/PatternObserver.aspx) that I've read regarding the observer design pattern stipulate that the concrete subject holds a reference to the concrete observer. Much like this:
class ConcreteObserver : IObserver
{
ConcreteSubject concreteSubjectInstance;
//other code, etc.
}
Now, if the concrete Subject is itself implements a Subject interface (or derives开发者_StackOverflow from some abstract Subject class) why not make the type in the ConcreteObserver be of that abstract/interface? I.e.
class ConcreteObserver : IObserver
{
ISubject concreteSubjectInstance;
//other code, etc.
}
Moreover, why not just make it a field in the (e.g.) IObserver
interface?
Ultimately, given that the pattern itself seems to loosen the coupling of the Subject to its Observers, why does this appear not to be promoted when coupling an Observer to its subject?
Or is it? I am only basing this on examples that I have read.
From your picture, your "update()" method does not receive any information about the state of the Subject, so, if the Observer needs information about this state (as usual in the observer pattern), then it must retrieve it from the ConcreteSubject invoking to the "GetState()" method (not present in ISubject).
An alternative to this schema, would be to pass the state (or a reference to the whole ConcreteSubject) as parameter of "update()" method.
Other general explanations to having a reference to ConcreteSubject instead of ISubject can be that you may want to interact with the ConcreteSubject to invoke business logic (of course not exposed in the ISubject interface).
Just because the definition you read states subject holds a reference to the concrete observer
doesn't mean you have to read it literally.
As long as the subject has a reference/link to the observer whether concrete or via an interface/class the statement remains true.
Its very common to see an interface on both side IObserver and IObservable. I think the issue you are going to find is that when you make subject abstract you are going to really have to try hard and find how to make your state generic.
Concrete Observer, and Concrete Subject implementation have state too. When state of subject is changes, state of concrete observer is updating too. But sometimes, you might need to see the state of subject, which you do not have, for this, you had better have reference to subject. In the other words, in order to see the state of concrete subject.
I will try to provide my point of view.
Why concrete? Won't they cause coupling between Subject and Observer?
The main concern of Observer Pattern is 1-to-N model, not N-to-N, and this is achieved by the Observer interface.
Yes, it causes coupling and it's intended, so each concrete observer will get exactly what he wants, without redundant "context passing".
Coupling is bad, but Principle > Decoupling.
If a concrete subject is accessed through the Subject interface, we can subscribe to different Subject at runtime! Right?
- No, for each concrete observer's
update()
, it should only do one thing. Single Responsibility Principle. - What if one wants to listen to many events? This can be done by Composition, not that lumping all the stuff in a single
update()
.
Some books/online resources authors make update()
into something like update(subject, context, varName, ...)
then they're assuming what an Observer would need, but
What an Observer will need is not a concern of the Subject, why not take it yourself?
Coupling ConcreteObserver to ConcreteSubject so the Subject's job is just sending notification, not the data.
Subject: Hey everyone my store is open!
ObserverA: OK, I think I need that iPhone.
ObserverB: OK, I think I need that Windows Computer.
ObserverC: I like both iPhone and Windows Computer, maybe I should ask A,B for the news.
agree with @Rainning, concrete observers may have interest in different fields from Observable. The observer can get what he wants in its own update method. here is an example for my studying 《head first design pattern》 with c++:
https://github.com/jwbecalm/Head-First-Design-Patterns-in-CPP/tree/main/ch02_Observer
also include plantuml class
精彩评论