Entwurfsmuster in TypeScript: Fortgeschrittenes Niveau mit Beispielen
\n\nDie Entwicklung komplexer Anwendungen in TypeScript erfordert nicht nur Kenntnisse der Syntax, sondern auch die Fähigkeit, eine flexible, skalierbare Architektur zu erstellen. Die GoF-Entwurfsmuster (Gang of Four) bleiben der Goldstandard, aber auf fortgeschrittenem Niveau wird ihre Anwendung subtiler. In diesem Artikel analysieren wir vier leistungsstarke Muster – Bridge, Visitor, State und Strategy – mit realen Beispielen in TypeScript. Sie erfahren, wie Sie strenge Typisierung, Generics und Schnittstellen zur Implementierung dieser Muster nutzen.
\n\n1. Bridge: Abstraktion von der Implementierung trennen
\n\nDas Bridge-Muster (Brücke) trennt die Abstraktion von ihrer Implementierung und ermöglicht es, beide unabhängig voneinander zu ändern. Dies ist besonders nützlich, wenn Sie mehrere Varianten von Funktionalitäten haben, die kombiniert werden können.
\n\nBeispiel: Ein System zum Rendern von Formen in verschiedenen Grafik-APIs (Canvas und SVG).
\n\n// Implementierung (Implementation)\ninterface Renderer {\n renderCircle(radius: number): void;\n renderSquare(side: number): void;\n}\n\nclass CanvasRenderer implements Renderer {\n renderCircle(radius: number): void {\n console.log(`Canvas: zeichne Kreis mit Radius ${radius}`);\n }\n renderSquare(side: number): void {\n console.log(`Canvas: zeichne Quadrat mit Seitenlänge ${side}`);\n }\n}\n\nclass SVGRenderer implements Renderer {\n renderCircle(radius: number): void {\n console.log(`SVG: <circle r="${radius}" />`);\n }\n renderSquare(side: number): void {\n console.log(`SVG: <rect width="${side}" height="${side}" />`);\n }\n}\n\n// Abstraktion (Abstraction)\nabstract class Shape {\n protected renderer: Renderer;\n\n constructor(renderer: Renderer) {\n this.renderer = renderer;\n }\n\n abstract draw(): void;\n}\n\nclass Circle extends Shape {\n private radius: number;\n\n constructor(renderer: Renderer, radius: number) {\n super(renderer);\n this.radius = radius;\n }\n\n draw(): void {\n this.renderer.renderCircle(this.radius);\n }\n}\n\nclass Square extends Shape {\n private side: number;\n\n constructor(renderer: Renderer, side: number) {\n super(renderer);\n this.side = side;\n }\n\n draw(): void {\n this.renderer.renderSquare(this.side);\n }\n}\n\n// Verwendung\nconst canvasCircle = new Circle(new CanvasRenderer(), 10);\ncanvasCircle.draw(); // Canvas: zeichne Kreis mit Radius 10\n\nconst svgSquare = new Square(new SVGRenderer(), 5);\nsvgSquare.draw(); // SVG: <rect width="5" height="5" />\n\nSchlüsselmerkmal: TypeScript stellt sicher, dass alle Implementierungen dem Vertrag Renderer folgen. Das Hinzufügen eines neuen Formtyps oder eines neuen Renderers bricht den vorhandenen Code nicht.
2. Visitor: Durchlaufen komplexer Strukturen ohne Änderung der Klassen
\n\nDas Visitor-Muster (Besucher) ermöglicht das Hinzufügen neuer Operationen zu Objekten, ohne deren Klassen zu ändern. Es ist eine ideale Lösung für die Arbeit mit Bäumen, ASTs (abstrakten Syntaxbäumen) oder Komponentenhierarchien.
\n\nBeispiel: Ein System zum Exportieren von Dokumentknoten in verschiedene Formate (JSON, XML).
\n\n// Elemente (Elements)\ninterface DocumentNode {\n accept(visitor: Visitor): void;\n}\n\nclass TextNode implements DocumentNode {\n constructor(public content: string) {}\n\n accept(visitor: Visitor): void {\n visitor.visitTextNode(this);\n }\n}\n\nclass ImageNode implements DocumentNode {\n constructor(public src: string, public alt: string) {}\n\n accept(visitor: Visitor): void {\n visitor.visitImageNode(this);\n }\n}\n\n// Besucher (Visitor)\ninterface Visitor {\n visitTextNode(node: TextNode): void;\n visitImageNode(node: ImageNode): void;\n}\n\nclass JSONExporter implements Visitor {\n private p