Consider this UML diagram (of the Observer pattern) taken from a YT tutorial video:
IObservable
has a dependency on IObserver
because its methods take an argument of that type. Concrete*
classes of course implement their respective interfaces. And ConcreteObserver
has a dependency on ConcreteObservable
(and not IObservable
, mind you) as it takes that as an argument in its constructor.
What doesn't feel right to me is that ConcreteObservable
needs to implement IObservable
's methods so it also "uses" IObserver
directly. Shouldn't there be a dependency between those on the diagram, like so?
I know that it's just implementing IObservable
's methods and the relation between ConcreteObservable
and IObserver
is kind of indirectly shown by the other arrows on the diagram but like I mentioned that doesn't feel right to me as there is a direct dependency between those and it's not shown on the diagram.
And just to clarify - I'm not talking about this concrete UML diagram in particular - this approach (with "missing" dependencies) seems to be the norm in most/all UML diagrams of similar class relations. Why is that?
CodePudding user response:
Why?
First of all, the diagram does not fully correspond to the narrative: the diagram shows a ConcreteObservable
that is a specialization of IObservable
(i.e. it inherits and not just implements). The same for ConcreteObserver
and IObserver
.
The UML semantics are pretty unambiguous: if ConcreteObserver
inherits from IConcreteObserver
, it inherits not only its public operations and properties, but also its relations. Therefore the red arrow would be redundant since it is already implicit. Moreover this redundancy would introduce an ambiguity: the expert reader would wonder if it's the same or another association on the top of the existing one. You'd need some more elements in this case to disambiguate (for example an inheritance arrow between the red association and the original association).
For interface realization (the line to the superclass should be dotted) it is similar: the class that realizes the interface must implement what the interface specifies, including its associations. So it's not inherited, but again, the association is implicit.
Get used to it!
But rather than adding unnecessary elements to the diagram, using advanced UML features to disambiguate, and thus making the diagram more difficult to read, I'd advise to get used to this kind of representation: you'll see a lot in your professional life and it is important to recognize the "pattern" (not necessarily the observer pattern here, but the more technique to decouple abstractions using interfaces or generalizations/specializations).