Cover Image

Composite

Lets you compose objects into tree structures and then work with these structures as if they were individual objects.

classDiagram
    class Component {
        <<interface>>
        +operation()
        +add(Component)
        +remove(Component)
        +getChild(int) Component
    }
    class Leaf {
        +operation()
    }
    class Composite {
        -List~Component~ children
        +operation()
        +add(Component)
        +remove(Component)
        +getChild(int) Component
    }

    Component <|.. Leaf
    Component <|.. Composite
    Composite o-- Component

When to use

Use the Composite pattern when you have to implement a tree-like object structure. Use when you want the client code to treat both simple and complex elements uniformly.

Explanation

Problem

Using the Composite pattern makes sense only when the core model of your app can be represented as a tree. For example, imagine that you have two types of objects: Products and Boxes. A Box can contain several Products as well as a number of smaller Boxes. These little Boxes can also hold some Products or even smaller Boxes, and so on.

Say you decide to create an ordering system that uses these classes. Orders could contain simple products without any wrapping, as well as boxes stuffed with products… and other boxes. How would you determine the total price of such an order?

Solution

The Composite pattern suggests that you work with Products and Boxes through a common interface which declares a method for calculating the total price.

For a product, it’s simply the product’s price. For a box, it’s the sum of the prices of all items (products or boxes) within that box. If one of these items were a smaller box, that box would also start going over its contents and so on, until the prices of all inner components were calculated.

Real world problem

  1. File System: Directories can contain Files and other Directories. You can treat both as a “Node” to ls, rm, or calculateSize.
  2. GUI Elements: A Panel can contain Buttons, TextFields, and other Panels. draw() on main Panel draws all children recursively.
  3. Army Hierarchy: General -> Colonels -> Captains -> Soldiers. order() trickles down.

Pros and Cons

Pros Cons
- Simplifies Client: You can work with complex tree structures more conveniently: use polymorphism and recursion to your advantage.
- Open/Closed Principle: You can introduce new element types into the app without breaking the existing code, which now works with the object tree.
- Interface issues: It might be difficult to provide a common interface for classes whose functionality differs too much. In certain scenarios, you’d need to overgeneralize the component interface, making it harder to comprehend.

Comparison

  • Decorator: Composite generally has many children; Decorator has one.
  • Chain of Responsibility: Request passes along a chain. Composite passes request down a tree.
  • Iterator: You can use Iterator to traverse Composite trees.

Code example

Typescript

Php