Comparison of your observer with the GoF pattern
In the GoF observer, notify()
is implemented in the abstract Subject
: the update()
function of all observers are called, up to them to decide if the object-update notification is relevant or not. In this way, the subject does not have to know anything specific about the observers.
First potential design issue
If you let Subject
decide which Observer
to notify, the subject might need to know additional details about the observer. Depending on what the subject needs to know about the observer for its decision making, this may or may not be ok:
- If the concrete subjects need to know about the concrete observers, the design would increase the coupling in a way that is not desirable. In fact, this goes against the open/close principle, since adding new kind of observers would require to adjust the concrete subjects. Maintenance nightmare in sight !
- If concrete subjects only need to know the interface of the abstract observer, your design would be ok. In the spirit of DRY I'd nevertheless suggest to combine this pattern with the template method pattern, to let the
notify()
be general, and make it dependent on an abstract condition that can change according to the concrete subject.
Second potential design issue
It seems that your concrete observers need to know the type of the subject in order to call the right update function. I'm not sure that it's really the case, but it's the impression coming your naming convention of updateXXX()
, because each XXX
is used in ony one subject.
If this is the case, the Observer
abstraction would depend on concrete implementation of Subject
. This does not seem a good idea: concrete classes may depend on abstract classes, but the contrary is against the open/close principle.
UML modelling issues
On the UML diagram, I would advise not to use the black composition diamond from Subject
to Observer
:
- composite (black diamond) means that the observers belong exclusively to the subject (i.e. if the subject is deleted, its observers would not survive). I doubt that it's the case here.
- aggregate (white diamond) would have a similar meaning but with a shared ownership (not exclusive). I cannot exclude this, but I see no compelling argument to use it here either.
- I would recommend a simple (one-to-many) association.
- If you leave the multiplicity of 1 on the side of the subject, your observer would have to register during its construction. Is it what you intend to implement, or should it be 0..1 ?
The navigable association from concrete observer to all the concrete subjects raises questions:
- is there a navigable association between the concrete observer and abstract subject ? (in this case draw the association with the abstract class, in order to be accurate)
- or are there 3 navigable associations: between the concrete observer and each of the concrete subjects ?
Think about the open/close principle in this regard. What would you expect to happen if you'd need to add a new concrete subject ? Would you have to change all the concrete observers (adding a new association) ? Or would you expect it to work without any change (because the association is with the abstract subject) ?