Structural PatternINTERMEDIATE7 min deep dive

Composite Pattern Pattern

Composes objects into tree structures to represent part-whole hierarchies, letting clients treat individual objects and compositions uniformly.

Real-World Mental Model / Metaphor:

A computer file system. A Folder can contain Files AND other Folders. Calling `getSize()` on a Folder computes the total size recursively, treating leaf files and container folders uniformly.

Interactive Runtime Simulator

Test and tweak inputs dynamically

Interactive Composite Pattern SimulatorLIVE PLAYGROUND

Interact with the controls below to see how this design pattern executes in memory at runtime.

Category: Structural
Configure Chain Handlers (Toggle Failures):
CHAIN PIPELINE STATUS
Step 1: AuthHandler.check() -> PASSED
Step 2: RateLimitHandler.check() -> PASSED
Step 3: PayloadGuard.check() -> PASSED
The Problem It Solves

Having to write separate recursive loops and type checks (`if (item instanceof Folder) ... else ...`) to calculate totals across nested trees.

The Architectural Solution

Define a common Component interface with shared operations. Both Leaf (file) and Composite (folder) implement the interface.

Pattern Structure & Participants

ParticipantRole & ResponsibilityType
FileSystemComponent (Interface)Common operation: getSize()interface
File (Leaf)Returns file byte size directlyclass
Directory (Composite)Contains children and sums their getSize()class
Collaboration Rules:
  • Directory contains a List<FileSystemComponent>
  • Client calls root.getSize() without caring about tree depth

Production Code Implementation

Composite Pattern.java
public interface FileSystemItem {
    long getSize();
    String getName();
}

public class FileItem implements FileSystemItem {
    private final String name;
    private final long sizeBytes;

    public FileItem(String name, long sizeBytes) {
        this.name = name;
        this.sizeBytes = sizeBytes;
    }
    public long getSize() { return sizeBytes; }
    public String getName() { return name; }
}

public class DirectoryItem implements FileSystemItem {
    private final String name;
    private final List<FileSystemItem> children = new ArrayList<>();

    public DirectoryItem(String name) { this.name = name; }
    public void add(FileSystemItem item) { children.add(item); }

    public long getSize() {
        return children.stream().mapToLong(FileSystemItem::getSize).sum();
    }
    public String getName() { return name; }
}
When to Use:
  • •When you have to implement a tree-like object structure.
  • •When you want the client code to treat both simple and complex elements uniformly.
When to Avoid (Anti-Pattern):
  • •When the tree elements share too few common operations, forcing awkward empty method implementations.

Staff Engineering Interview Insights & Gotchas

  • Mention file systems, org charts, and DOM trees as the top 3 textbook examples of Composite.