Introduction

Many real‑world models are naturally hierarchical:

  • File systems: folders inside folders, containing files

  • UI components: windows containing panels, buttons, labels

  • Organization charts: departments containing teams, containing people

You often want to:

  • Operate on a single item (e.g., a file)

  • Or on a group of items (e.g., a folder with many files and subfolders)

Without writing separate logic for “single” vs “group” each time.

The Composite Design Pattern addresses this by making individual objects and groups implement the same interface, so client code can treat them uniformly.


Intent of the Composite pattern

The core intent:

Compose objects into tree structures and let clients treat individual objects and compositions of objects uniformly.

Key ideas:

  • Define a common interface for both simple (leaf) and complex (composite) objects.

  • A leaf represents a single object (e.g., a file).

  • A composite contains children (leaf or composite) and implements operations by delegating to its children.

  • Client code uses the common interface and doesn’t care whether it’s dealing with a single item or an entire subtree.

In short: “Call operation() On one object or on a whole tree, the calling code looks the same.”


Basic structure: Component, Leaf, Composite

Typical roles:

  • Component

    • The base interface or abstract class.

    • Declares operations that both leaves and composites support.

  • Leaf

    • Represents end objects (no children).

    • Implements operations directly.

  • Composite

    • Holds a collection of Component* 

    • Implements operations by iterating over its children and delegating calls.


C++ example: File system (folders and files)

Step 1: Component interface


The show function prints the node with indentation to reflect the tree structure.

Step 2: Leaf – File


Step 3: Composite – Folder


Step 4: Using the composite


Here:

  • File is a leaf.

  • Folder is a composite.

  • Both implement FileSystemNode.

  • Client code works with FileSystemNode* and calls show() On either a file or a folder (or the whole tree) in the same way.


Why is composite useful

Composite simplifies client code and makes hierarchies easy to work with:

  1. Uniform treatment

    • Client code does not need if (isFolder) ... else ....

    • It just calls node->show()  node->operation() Regardless of whether it’s a leaf or composite.

  2. Natural match for trees

    • Any structure that forms a tree (UI, menus, documents with sections) can be modeled cleanly.

  3. Recursive operations

    • Operations naturally propagate down the tree: “print everything”, “calculate total size”, “apply permission changes to all children”, etc.

  4. Flexible composition

    • You can nest composites inside composites (folders inside folders) without changing client code.

Composite often appears in frameworks and libraries that deal with nested structures, such as UI toolkits (containers containing widgets which can themselves be containers).


Another example: Graphic objects (shapes and groups)

Think of a drawing application:

  • Leaf: individual shapes like Circle, Rectangle.

  • Composite that can contain multiple shapes or groups.

Common interface:


Leaf:


Composite:


Usage:


Again, client code uses Graphic* and can draw a single shape or a whole group with one call.


When to use Composite (and when not to)

Use Composite when:

  • You have data that is naturally hierarchical or tree‑like.

  • You want the ability to treat a single object and a group of objects the same way.

  • Operations on the whole structure can be defined recursively (e.g., print, compute total, apply an action).

Be cautious or avoid Composite when:

  • The hierarchy is very simple and unlikely to grow; a plain container might be enough.

  • You don’t need uniform treatment; leaf and composite behavior are completely different and will always be handled separately.

  • The operations you need are very diverse and don’t fit well into one common interface.

As with other patterns, avoid overuse; apply Composite when it aligns with the problem’s structure.


Summary

The Composite Design Pattern is a structural pattern that:

  • Models part‑whole hierarchies as tree structures.

  • Let clients treat individual objects (leaves) and groups of objects (composites) uniformly through a common interface.

  • Naturally supports recursive operations over the whole structure.

You saw:

  • A C++ file system example (File and Folder) using a FileSystemNode interface.

  • How a Folder holds children and delegates operations like show() to them.

  • A graphics example where GraphicGroup Manages multiple shapes.

  • When Composite is a good fit in Low Level Design, especially for menus, file systems, UI trees, or organizational structures.