Composite-Muster
Das Composite-Muster erlaubt es, einzelne Objekte und Gruppen von Objekten einheitlich über eine gemeinsame Schnittstelle zu behandeln. Verwende es, wenn deine Daten einen Baum bilden — Dateien und Ordner, UI-Knoten, organisatorische Hierarchien — und Aufrufer sich nicht darum kümmern sollten, ob sie mit einem Blatt oder einem Zweig sprechen.
Überblick
Das Composite-Muster modelliert Teil-Ganzes-Hierarchien, indem Blätter und Container dieselbe Schnittstelle erhalten. Ein Ordner verhält sich wie eine Datei: Beide haben ein size(), beide können gerendert werden. Die Implementierung des Containers delegiert einfach an seine Kinder und aggregiert die Ergebnisse. Der gesamte Teilbaum wird rekursiv manipulierbar, ohne dass der Client ein einziges isFolder schreibt.
Wann verwenden
- Deine Domäne ist ein Baum (DOM, Dateisystem, Menüstruktur, Organigramm).
- Aufrufer sollen ein einzelnes Element oder einen ganzen Teilbaum auf dieselbe Weise bearbeiten können.
- Mit der Zeit kommen neue Blatt- oder Composite-Typen hinzu und du willst, dass sie sich einfügen, ohne Aufrufer anzufassen.
Beispiel
interface FileSystemNode {
size(): number;
}
class FileNode implements FileSystemNode {
constructor(private readonly bytes: number) {}
size() { return this.bytes; }
}
class FolderNode implements FileSystemNode {
private children: FileSystemNode[] = [];
add(node: FileSystemNode) { this.children.push(node); return this; }
size() { return this.children.reduce((sum, c) => sum + c.size(), 0); }
}
const root = new FolderNode()
.add(new FileNode(120))
.add(
new FolderNode()
.add(new FileNode(50))
.add(new FileNode(30))
);
console.log(root.size()); // 200Vorteile
- Aufrufer arbeiten gegen eine einzige Schnittstelle — keine isLeaf-Verzweigung.
- Das Hinzufügen eines neuen Knotentyps zieht keine Wellen durch den Codebase.
- Rekursive Operationen (Größe, Render, Suche) lassen sich trivial ausdrücken.
Nachteile
- Die gemeinsame Schnittstelle kann zu generisch werden, mit Methoden nur für Blätter oder nur für Composites.
- Die Struktur ist auf Typebene schwer einzuschränken (z. B. "ein Ordner darf nur Dateien vom Typ X enthalten").
- Übermäßige Rekursion auf tiefen Bäumen kann die Performance beeinträchtigen oder den Stack überlaufen lassen.