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
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.
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 with practical examples. Add new operations to object structures without modifying existing classes 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.