Search code examples
design-patternsiteratorumlsoftware-designclass-diagram

Why are there different ways to describe same design pattern using UML? What to trust?


I find it difficult to learn both Design Pattern and UML since there are different ways to describe the same pattern which make me unsure what is the single source of truth.

Take Iterator pattern for example, here are just a few diagrams that I saw from well-known sites:

1 WIKIPEDIA

https://en.wikipedia.org/wiki/Iterator_pattern

enter image description here

2 TUTORIALS POINT

https://www.tutorialspoint.com/design_pattern/iterator_pattern.htm

enter image description here

3 REFACTORING GURU

https://refactoring.guru/design-patterns/iterator

enter image description here

4 OODESIGN

https://www.oodesign.com/iterator-pattern.html

enter image description here

5 HOWTODOINJAVA

https://howtodoinjava.com/design-patterns/behavioral/iterator-design-pattern/

enter image description here

What confuses me the most is how arrow symbols are used to describe the relationship between these classes. Sometimes they are generalization, sometimes interface realization, directed association or dependency. Even composition is also used...

I wonder what would be the best way for me to get my head around all this.


Solution

  • In general, one needs to be very careful when looking at UML models for design patterns. There are three reasons:

    • The reference for design patterns is the GoF. This book was published in 1995, before UML even existed, and used a variation of the OMT notation (an ancestor of UML). In case if doubts, this is the source to trust.
    • The Java language design was made public in 1995, JDK 1.0 release in January 1996, and the language not yet widely known. The authors based their designs and code examples on a C++ class model, i.e. on classes and inheritance only, without bothering for multiple inheritance. Most modern languages do not support multiple inheritance. As a consequence, some of the original patterns have to be adapted for Java, C# or Swift, to make a distinction between classes, abstract classes and interfaces, and between inheritance and interface implementation. There are multiple ways to do this. For example, some systematically converted abstract classes to interfaces. Some converted them only when there was a conflict. And some converted according to the interface "spirit".
    • Misunderstandings happen. Some people publish such diagrams on the net but misunderstand the pattern, or misunderstand UML, or both together. Also, Gamma et al started the book when they were PhD students and also made some mistakes. You'll find for example some inconcsitencies in their use of the OMT aggregation.
    • The worst case is the Builder pattern, where you have not only those problems, but on top of that you have a naming conflict: a very popular Java book introduced a (very different) variant of the builder pattern, with a different intent and another design, which caused total confusion.

    Now to your specific example, and based on the content you have provided:

    • oodesign is the closest to the original pattern and fully accurate. Btw, I mostly use links to their pages when it comes to patterns.
    • refactoring guru is also a good choice. They opted to use interfaces instead of abstract classes, which is fine. But they have redefined the interface's operations and properties (probably in relation to own examples) and require a bidirectional navigation that seems not justified. If you're interested, there is a "Head First: Design patterns" which uses a similar mapping but keeps the original interface.
    • wikipedia is not bad either: they have left out the client (which the GoF showed in light gray, to suggest that it's not essential for this pattern); They are more precise and complete on dependencies; But they also redefined the operations and properties differently. And they added an unnecessary aggregation symbol.
    • How to make it in Java is confusing, because they kept one abstract class and opted for an interface for the other. And they have hidden the operations and properties. But there's nothing fundamentally wrong at first sight.
    • Forget about tutorial points, at least for this UML diagram. It's plain wrong, as @qwerty_so already mentioned in the comments.

    The statement of accuracy is for this pattern only and for the current version of the content. This cannot be generalized to all the design patterns in view of my introductory remarks.