The Composite pattern composes objects into tree structures to represent part-whole hierarchies, letting clients treat individual and composite objects uniformly.

Problem

You need to represent a tree structure where both leaf nodes and branches are treated the same way.

Solution

  interface FileSystemNode {
    String getName();
    long getSize();
    void print(String indent);
}

class File implements FileSystemNode {
    private final String name;
    private final long size;

    File(String name, long size) {
        this.name = name;
        this.size = size;
    }

    public String getName() { return name; }
    public long getSize() { return size; }

    public void print(String indent) {
        System.out.println(indent + "📄 " + name + " (" + size + " bytes)");
    }
}

class Directory implements FileSystemNode {
    private final String name;
    private final List<FileSystemNode> children = new ArrayList<>();

    Directory(String name) { this.name = name; }

    void add(FileSystemNode node) { children.add(node); }

    public String getName() { return name; }
    public long getSize() {
        return children.stream().mapToLong(FileSystemNode::getSize).sum();
    }

    public void print(String indent) {
        System.out.println(indent + "📁 " + name);
        children.forEach(c -> c.print(indent + "  "));
    }
}

// Usage
Directory root = new Directory("project");
root.add(new File("README.md", 1024));
Directory src = new Directory("src");
src.add(new File("Main.java", 2048));
root.add(src);
root.print("");
  

Java Examples

  // AWT/Swing Component tree
JPanel panel = new JPanel();
panel.add(new JButton("Click"));
panel.add(new JLabel("Hello"));

// JavaFX Scene Graph
Group root = new Group();
root.getChildren().addAll(new Rectangle(), new Circle());

// Menu systems
Menu fileMenu = new Menu("File");
fileMenu.add(new MenuItem("Open"));
fileMenu.add(new MenuItem("Save"));
  

Composite vs Decorator

Composite Decorator
Tree structure (has-a children) Single wrapper chain
Part-whole hierarchy Adds behavior
Uniform interface for leaves and composites Same interface, enhanced behavior

When to Use

  • Tree-structured data (file systems, org charts, UI components, menus)
  • Clients should ignore leaf vs composite differences
  • Operations should propagate through the entire tree

Best Practices

  • Keep the component interface simple — getSize(), render(), add()
  • Decide where to store children — only in composite class
  • Consider whether add()/remove() belong in the leaf interface (some designs use a separate Composite interface)
  • Use streams for recursive operations on the tree