Skip to contentJMRG
All posts

Composite Pattern: Uniform Hierarchical Structures

design-patternsstructuralcomposite

Intent

Composite lets you treat individual objects and compositions of objects uniformly. It composes objects into tree structures to represent part-whole hierarchies.

The Problem

Without Composite, client code needs to distinguish between simple and composite objects:

// Complex client code
function calculatePrice(item: unknown): number {
  if (item instanceof Product) {
    return item.price;
  } else if (item instanceof Box) {
    let total = 0;
    for (const child of item.children) {
      total += calculatePrice(child); // Manual recursion
    }
    return total;
  }
}

The Solution: Composite

classDiagram
    class Component {
        <<interface>>
        +operation(): number
    }

    class Leaf {
        +operation(): number
    }

    class Composite {
        -children: Component[]
        +operation(): number
        +add(child: Component)
    }

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

TypeScript Implementation

// Base component
interface FileSystemNode {
  getName(): string;
  getSize(): number;
}

// Leaf: File
class File implements FileSystemNode {
  constructor(private name: string, private size: number) {}

  getName(): string {
    return this.name;
  }

  getSize(): number {
    return this.size;
  }
}

// Composite: Directory
class Directory implements FileSystemNode {
  private children: FileSystemNode[] = [];

  constructor(private name: string) {}

  getName(): string {
    return this.name;
  }

  getSize(): number {
    return this.children.reduce((sum, child) => sum + child.getSize(), 0);
  }

  add(node: FileSystemNode): this {
    this.children.push(node);
    return this;
  }
}

// Usage - Client treats everything uniformly
const root = new Directory('project')
  .add(new File('package.json', 1024))
  .add(new Directory('src').add(new File('index.ts', 512)));

console.log(`Total: ${root.getSize()} bytes`);

When to Use

Situation Recommendation
Tree structures (DOM, FS) ✅ Recommended
Menus with submenus ✅ Recommended
Arithmetic expressions ✅ Recommended
Flat structures without hierarchy ❌ Unnecessary

Conclusion

Composite simplifies client code by allowing you to treat individual elements and groups the same way.