# Purpose
The Composite pattern is a structural design pattern that allows composing objects into tree structures to represent part-whole hierarchies.
The goal is to allow clients to treat individual objects and compositions of objects uniformly. It is especially useful for modeling and working with complex structures.
# Problem
Building complex objects composed of simpler parts, and how to treat both the individual parts and the whole in a uniform manner.
# Solution
The solution proposed by the Composite is:
-
Divide objects into two categories: leaves (individual objects) and composites (objects with sub-objects).
-
Common Interface: Provides a common interface to treat both types, simplifying working with tree structures.
# Structure
# Participants
- Component: Common interface for individual objects and compositions.
- Leaf: Represents individual objects without children.
- Composite: Defines behavior for components having children.
- Client: Interacts with objects through the Component interface.
# When to Use It
-
To represent part-whole hierarchies of objects.
-
So clients can ignore the difference between compositions of objects and individual objects.
# Advantages
-
verified
Simplicity: Treat simple and composite objects equally.
-
verified
Flexibility: Allows building complex hierarchical structures.
-
verified
Extensibility: Easy to add new types of components.
# Disadvantages
-
warning
Restrictions: Hard to restrict component types.
-
warning
Performance: Issues with very large tree structures.
# Example: File System
We need to develop a management module that must organize and manipulate a large number of documents and folders.
Problem
Treating files and folders uniformly is a challenge because of their part-whole hierarchy.
Proposed solution
We use the Composite pattern to treat files (Leaf) and folders (Composite) uniformly under the FileSystemComponent interface.
# Java Code
interface FileSystemComponent {
void printName();
void add(FileSystemComponent component) throws Exception;
}
class File implements FileSystemComponent {
private String name;
public File(String name) { this.name = name; }
public void printName() { System.out.println("File: " + name); }
public void add(FileSystemComponent comp) { throw new UnsupportedOperationException(); }
}
class Directory implements FileSystemComponent {
private List children = new ArrayList<>();
public void add(FileSystemComponent comp) { children.add(comp); }
public void printName() {
for (FileSystemComponent child : children) child.printName();
}
}
# Mapping Participants
- FileSystemComponent (Component): Common interface.
- File (Leaf): Individual element.
- Directory (Composite): Container element.
- Client: Interacts through the common interface.
# Conclusions
The system becomes simpler and more scalable by allowing new operations or types of elements to be added without altering existing logic.
# Related Patterns
Decorator
Often used with Composite to add responsibilities.
Flyweight
Can be combined to share components.