The Composite Design Pattern: Trees Everywhere
Master the Composite Pattern in Java. Learn how to treat individual objects and compositions uniformly using recursive tree structures.
Moshiour Rahman
Advertisement
The Problem: Individual vs Groups
Imagine you are building a File System. You have File objects and Folder objects.
- A
Filehas a size. - A
FoldercontainsFilesand otherFolders.
How do you calculate the size of a Folder? You need to:
- Sum the sizes of all the
Files. - Recursively sum the sizes of all child
Folders.
If you treat File and Folder as completely different types, your code becomes messy with instanceof checks.
The Solution: The Composite Pattern
The Composite Pattern lets you compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly.
Real-Life Analogy: An Organization Chart 🏢
- Employee (Leaf): A developer with no reports.
- Manager (Composite): Has a list of employees under them.
When you ask “What’s your team’s total salary?”, you:
- Employee: Returns their own salary.
- Manager: Sums salaries of all their reports (recursively).
The magic? Both Employee and Manager implement the same getSalary() method.
Visualizing the Pattern

Implementation
1. The Component Interface
public interface FileSystemNode {
int getSize();
void print(String indent);
}
2. Leaf (The Simple Object)
public class File implements FileSystemNode {
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
@Override
public int getSize() {
return size; // Just return own size
}
@Override
public void print(String indent) {
System.out.println(indent + "File: " + name + " (" + size + " bytes)");
}
}
3. Composite (The Container)
import java.util.ArrayList;
import java.util.List;
public class Folder implements FileSystemNode {
private String name;
private List<FileSystemNode> children = new ArrayList<>();
public Folder(String name) {
this.name = name;
}
public void add(FileSystemNode node) {
children.add(node);
}
@Override
public int getSize() {
int total = 0;
for (FileSystemNode child : children) {
total += child.getSize(); // Recursive!
}
return total;
}
@Override
public void print(String indent) {
System.out.println(indent + "Folder: " + name);
for (FileSystemNode child : children) {
child.print(indent + " "); // Recursive!
}
}
}
Usage
FileSystemNode file1 = new File("file1.txt", 100);
FileSystemNode file2 = new File("file2.txt", 200);
Folder documents = new Folder("Documents");
documents.add(file1);
documents.add(file2);
Folder photos = new Folder("Photos");
photos.add(new File("pic1.jpg", 500));
Folder root = new Folder("Root");
root.add(documents);
root.add(photos);
System.out.println("Total size: " + root.getSize()); // 800
root.print("");
In The Wild (Real World Examples)
1. GUI Frameworks (Swing, JavaFX)
A Container (like JPanel) can hold Component objects (like JButton or other JPanel containers).
Both implement Component, so you can call setVisible() on a single button or a whole panel tree.
2. AST (Abstract Syntax Trees) in Compilers
An expression like 2 + (3 * 4) is a tree:
+is a composite (has left and right children).2,3,4are leaves (numbers).
The evaluate() method is recursive, just like our file size example.
Cheat Sheet
| Feature | Details |
|---|---|
| Category | Structural |
| Problem Solved | Treating part-whole hierarchies uniformly |
| Key implementation | Recursive structures (Tree) |
| Pros | Simplicity (Client doesn’t need to know if it’s dealing with a leaf or composite) |
| Cons | Overly general (Hard to restrict what children a composite can have) |
Tips to Remember 🧠
- “Matryoshka Doll Again”: Like a folder containing folders containing files.
- “Recursion”: If you see recursive calls on
children, it’s likely Composite.
Advertisement
Moshiour Rahman
Software Architect & AI Engineer
Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.
Related Articles
The Visitor Design Pattern: Add Operations Without Modifying Classes
Master the Visitor Pattern in Java. Learn how to add new operations to object structures using double dispatch.
JavaThe Template Method Pattern: The Recipe for Success
Master the Template Method Pattern in Java. Learn how to define the skeleton of an algorithm in a superclass but let subclasses override specific steps.
JavaThe Strategy Design Pattern: Kill the If-Else Statements
Master the Strategy Pattern in Java. Learn how to replace complex if-else logic with interchangeable algorithms and follow the Open/Closed Principle.
Comments
Comments are powered by GitHub Discussions.
Configure Giscus at giscus.app to enable comments.