Composite Pattern
Compose objects into tree structures to represent part-whole hierarchies
Pattern Overview
π³ Composite Pattern
The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly.
Core Concepts
πΉ Component Interface - Common interface for all objects in the tree
πΉ Leaf - Individual objects with no children
πΉ Composite - Objects that can contain other components
πΉ Uniform Treatment - Same operations work on both leaves and composites
Real-World Applications
File Systems - Files and folders both support operations like size calculation UI Components - Individual elements and containers both render content Expression Trees - Numbers and operations both evaluate to values Organization Charts - Employees and departments both have hierarchical operationsImplementation Benefits
β
Simplifies client code - Same interface for simple and complex objects
β
Easy to add new components - Just implement the component interface
β
Recursive operations - Operations naturally work on entire trees
β
Flexible structure - Can build complex hierarchies dynamically
Examples:
const project = createFileSystem();
console.log(project.display());
console.log(`Total size: ${project.getSize()}KB`);π project/ (7KB total)
π src/ (4KB total)
π components/ (3.5KB total)
π Button.tsx (2KB)
π Input.tsx (1.5KB)
π index.ts (0.5KB)
π package.json (1KB)
π README.md (2KB)
Total size: 7KBconst app = createUITree();
console.log(app.render());<div><header><button>Home</button><button>About</button></header><main><section></section></main></div>const expr = createExpressionTree();
console.log(`Expression: ${expr.toString()}`);
console.log(`Result: ${expr.evaluate()}`);Expression: ((3 + 4) * (2 - 1))
Result: 7Concepts
Complexity Analysis
Implementation
file-system
// File System Composite Implementation
interface FileSystemComponent {
getName(): string;
getSize(): number;
display(indent?: string): string;
}
class File implements FileSystemComponent {
constructor(private name: string, private size: number) {}
getName(): string {
return this.name;
}
getSize(): number {
return this.size;
}
display(indent = ''): string {
return `${indent}π ${this.name} (${this.size}KB)`;
}
}
class Folder implements FileSystemComponent {
private children: FileSystemComponent[] = [];
constructor(private name: string) {}
getName(): string {
return this.name;
}
getSize(): number {
return this.children.reduce((total, child) => total + child.getSize(), 0);
}
add(component: FileSystemComponent): void {
this.children.push(component);
}
display(indent = ''): string {
let result = `${indent}π ${this.name}/ (${this.getSize()}KB total)`;
for (const child of this.children) {
result += '
' + child.display(indent + ' ');
}
return result;
}
}