- Intent: Compose objects into tree structures to represent part-whole hierarchies and let clients treat individual objects and compositions uniformly
Structure §
Image from: Gamma, Helm, Johnson, and Vissides
Image from: Gamma, Helm, Johnson, and Vissides
Applicability §
- You want to represent part-whole hierarchies of objects.
- You want clients to ignore the differences between compositions of objects and individual objects.
Consequences §
- Defines class hierarchies consisting of primitive objects and composite objects.
- Makes the client simple as composites and primitives are treated the same.
- Makes it easier to add new kinds of components.
- Can make the design overly general. Making it so only certain components are present is difficult.
Implementation §
Parent References §
- Simplifies the traversal from parent to leaf
- Define the parent reference in the Component class.
- Change the parent of the component only when it is being added or removed.
Sharing components §
- Children can store multiple parents, but this can lead to ambiguities.
Use Common Denominators §
- Maximize component interface by defining as many common operations for Composite and Leaves.
Declaring child management operations §
- Declare operations in the component which are inherited by the leaves (more transparent but less safe)
- Declare operations in the composites (safer but less transparent due to differing interfaces)
- Declare an operation to convert a component to a composite.
Considerations §
- Implementing a list of children in the base class incurs a space penalty for every leaf.
- Children can be ordered
- Caching to save time in search and traversal.
- Consider who should delete components (usually best to make the component responsible for deleting its children).
- Use data structures