5

The Wikipedia article on the Composite Design Pattern includes the following diagram:

UML Composite design pattern

As you see, there is an association relationship which is child 0..* – 1 parent (association).

However, shouldn't it be a composition relationship instead (filled diamond)? To me, it is nonsensical to consider the identity of a node in the tree in an isolated manner. If it loses its parent, then it loses its identity.

Or maybe I'm wrong? What do you think?

Aldan Creo
  • 181
  • 5

3 Answers3

4

The composite pattern does not assume that it's an UML composition (black diamond) in the general case: The UML composition implies ownership, i.e. responsibility for the lifecycle of the composed objects. But the composite pattern gives this responsibility to the client (not shown in your diagram, but on page 164 of the GoF). This is why the Composite offers an interface allowing to add() and remove() components.

You could certainly think of some variants where composites could be responsible for their components. But this is left open in the general pattern. So the use of UML composition would be a special, more restrictive case.

Not related: the composite diagrams often use a shared aggregation (hollow diamond). This is a legacy from GoF which did all the modeling using the OMT notation. In UML, the shared aggregation is not wrong, but the UML specification does not define any semantics for shared aggregation, so a simple association could be used as well.

Christophe
  • 74,672
  • 10
  • 115
  • 187
2

To me, it is nonsensical to consider the identity of a node in the tree in an isolated manner.

Consider, for example, a drawing (or diagramming) application that lets you stamp out a number of shapes (boxes, arrows, whatnot). Each shape is an object that has its own properties (size, color) and operations (scale, rotate, etc.).

Now, suppose the application allows you to group these objects together. This group, this new, more complex picture, is a composite, and each individual object in the group can be seen as a "node". The key feature of the pattern is that it allows you to manipulate the group the same way you'd manipulate a standalone shape.

enter image description here
(Image modified from sources here)

So you see, while it's a tree of objects, the leaf nodes are not nonsensical on their own (and can in fact be used in a standalone way).Of course, the pattern could be applied in a domain that has nothing to do with diagramming. There may be no visual representation involved.

The point is not to make a tree (that is, although you do end up with a tree of objects, the key motivation behind the pattern is not specifically to make a tree data structure). The idea is to facilitate combining elements (or behaviors) that are already useful on their own into a more complex element (or behavior) that can be treated the same way as the standalone stuff by the calling code (since it has the same public interface).

In my example above, the code that allows the user to examine the properties of the objects, and to manipulate them, makes no distinction between simple shapes and composite (grouped) shapes - it just works with the "Component" interface, and it doesn't care what kind of component it is.

Filip Milovanović
  • 8,428
  • 1
  • 13
  • 20
0

I agree that if a child loses its parent that it loses its identity as part of a wider hierarchy. However, that alone is not good enough reason to destroy the child. You might still have plans for it despite it no longer being part of the tree.

It's not safe for the spec to assume a child must die if disconnected from the tree.

Lloyd
  • 101
  • 2