← Home
🏗Crack System Design with DSA AnimatorSystem DesignNEW
🏗 System Design›Structural Patterns

🌳Composite Pattern

Compose objects into tree structures to represent part-whole hierarchies — treat individual objects and compositions uniformly.

📌 Key IdeaDefine a Component interface for both leaf and composite nodes. Clients call operation() without caring if the node is a single item or a subtree (filesystems, UI trees, org charts).
🖼

Visual

🌳 Same operation on leaf and branch
  interface Node { long size(); }

  class File implements Node { ... }
  class Folder implements Node {
      List<Node> children;
      long size() { return children.stream().mapToLong(Node::size).sum(); }
  }

Recursive structure — composites delegate to children.

✅

When to Use

  • Tree or recursive structures: GUI widgets, JSON/XML DOM, file systems.
  • You want polymorphic behaviour across whole vs part (draw(), save()).
  • Need to ignore distinction between leaf and container in client code.
🚫

When NOT to Use

  • Flat lists only — composite adds useless indirection.
  • Type-specific behaviour dominates — too many instanceof checks smell.
🚨

Anti-Pattern (What NOT to Do)

Client walks tree with instanceofBadjava
long size(Object node) {
    if (node instanceof File f) return f.bytes();
    if (node instanceof Folder d) {
        long s = 0;
        for (Object c : d.children) s += size(c);
        return s;
    }
    throw new IllegalArgumentException();
}
Works once — adding new node type breaks every visitor-style caller.
✅

The Right Way

Node interface — recursion uniformGoodjava
interface Node { long size(); }

record File(String name, long bytes) implements Node {
    public long size() { return bytes; }
}

final class Folder implements Node {
    private final List<Node> children = new ArrayList<>();
    public long size() {
        return children.stream().mapToLong(Node::size).sum();
    }
}
New leaf/composite types implement Node — client calls size() blindly.
⚖️

Pros & Cons

👍 Pros
  • Simplifies client — uniform interface.
  • Easy to add new leaf or composite types.
  • Natural fit for recursive algorithms.
👎 Cons
  • Can over-generalize — operations that only make sense on leaves need guards or optional methods.
  • Harder to restrict composition (e.g. only folders hold children) — type design matters.
🔀

Common Confusions Cleared Up

Composite vs Decorator

Composite builds tree structure (children collection). Decorator wraps one object to add duties. Both can nest — intent differs: whole-part vs enhancement.

🎤

Interview Q&A

🔮

Likely Follow-up Questions

  • Iterator over composite tree — external vs internal?
  • How does Visitor pair with Composite?
🧾

Quick Cheat Sheet

IntentUniform treatment of leaf & branch.
Classic useFS, UI trees, org charts.
RiskInvalid ops on wrong node type.
🔗

Related Topics