On this page
Composite
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