Zum Inhalt springen

11. Entwurfsmuster I – Muster-Idee und SOLID im Überblick

Zu Zen-Modus wechseln

Nach diesem Kapitel kannst du:

  • erklären, was ein Entwurfsmuster ist, und den Nutzen von Mustern als gemeinsames Vokabular begründen.
  • ein Entwurfsmuster von einer Bibliothek unterscheiden und die drei Musterkategorien (Erzeugung, Verhalten, Struktur) mit Beispielen nennen.
  • die fünf SOLID-Prinzipien mit ihrem Kerngedanken nennen und einer typischen Code-Review-Aussage zuordnen.
  • beurteilen, warum SOLID ein Kompass und keine Checkliste ist.

Stell dir ein Fußballteam vor. Der Trainer ruft von der Seitenlinie: “Eckball, Variante 2!” Niemand fragt nach, niemand braucht eine Skizze. Spieler A spielt kurz an, Spieler B stellt den Block, Spieler C rückt nach. Der Name steht für einen Ablauf, den alle eingeübt haben. Ohne den Namen müsste der Trainer jedes Mal alle Laufwege erklären, und bis dahin ist die Gelegenheit vorbei.

Der Trainer ruft Eckball Variante 2, und jede Spielerin und jeder Spieler weiß, was zu tun ist

Mit Entwurfsmustern ist es dasselbe. Ein Muster ist keine Bibliothek und kein Codebaustein zum Kopieren, sondern eine benannte, bewährte Lösung für ein wiederkehrendes Entwurfsproblem. Der Nutzen liegt zu gleichen Teilen in der Lösung und in ihrem Namen. Dabei hinkt der Vergleich an einer Stelle: Eine Standardsituation wird exakt so gespielt, wie sie eingeübt wurde. Ein Muster dagegen wird an dein Problem angepasst, nicht eins zu eins nachgebaut.

Die Kapitel 11 bis 16 bilden zusammen den Block Entwurfsmuster I. Zuerst die Muster-Idee und die SOLID-Prinzipien im Überblick (dieses Kapitel), dann die fünf Prinzipien im Detail (S und O in Kapitel 12, L in Kapitel 13, I und D in Kapitel 14). Sie erklären, warum Muster so aussehen, wie sie aussehen. Danach zwei Erzeugungsmuster, die beantworten, wer entscheidet, welches Objekt entsteht: Singleton (genau eine Instanz, Kapitel 15) und Factory (die passende Klasse je nach Eingabe, Kapitel 16). Beide begegnen dir im Spiel wieder: Der Schiedsrichter ist ein Singleton, die Auswechselbank eine Factory.

flowchart LR
  accTitle: Der Block Entwurfsmuster I von der Muster-Idee über SOLID zu den Erzeugungsmustern
  K11["Kapitel 11: Muster-Idee, SOLID im Überblick"] --> K12["Kapitel 12: S und O"]
  K12 --> K13["Kapitel 13: L"]
  K13 --> K14["Kapitel 14: I und D"]
  K14 --> K15["Kapitel 15: Singleton"]
  K15 --> K16["Kapitel 16: Factory und Registry"]
  • Entwurfsmuster (design pattern): benannte, bewährte Lösung für ein wiederkehrendes Entwurfsproblem.
  • Gang of Four (GoF): die vier Autoren des Buchs Design Patterns (1994), nach dem die klassischen Muster benannt und eingeteilt sind.
  • Kopplung (coupling): wie stark ein Codeteil von einem anderen abhängt. Je loser, desto leichter lässt sich eines ändern, ohne das andere zu brechen.
  • Abstraktion: ein Interface oder eine abstrakte Klasse, die beschreibt, was möglich ist, ohne zu sagen, wie.
  • SOLID: Merkwort für fünf Prinzipien objektorientierten Entwurfs (Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, Dependency Inversion).
  • Singleton: Erzeugungsmuster, das sicherstellt, dass es von einer Klasse genau eine Instanz gibt (Kapitel 15).
  • Factory (Fabrik): Erzeugungsmuster, bei dem eine eigene Stelle anhand einer Eingabe entscheidet, welche konkrete Klasse entsteht (Kapitel 16).
  • Registry: eine Tabelle, in die sich Varianten eintragen und aus der eine Factory die passende auswählt (Kapitel 16).
  • Dependency Injection: Abhängigkeiten werden von außen übergeben, statt dass eine Klasse sie selbst erzeugt oder per getInstance() holt (Kapitel 14 und 15).

Der praktische Wert von Mustern zeigt sich in Gesprächen. “Wir brauchen an dieser Stelle eine Factory, die je nach Medientyp den passenden Verarbeiter liefert” - dieser eine Satz ersetzt eine halbe Stunde Erklärung, wenn beide Seiten das Muster kennen. Muster sind Fachvokabeln unter Entwicklerinnen und Entwicklern. Genau deshalb sind sie prüfungsrelevant: In einem Fachgespräch ist “das habe ich als Strategy gelöst” eine dichtere Aussage als drei Minuten Code-Vorlesen.

Historisch gehen die klassischen Muster auf ein Buch von vier Autoren zurück, die als Gang of Four bekannt wurden. Deren Einteilung nach Zweck ist bis heute die übliche Landkarte:

KategorieFrageBeispiele in den nächsten Kapiteln
ErzeugungWie werden Objekte erzeugt?Singleton, Factory
VerhaltenWie arbeiten Objekte zusammen?Observer, Strategy, Command
StrukturWie werden Objekte zusammengesetzt?Adapter, Decorator
flowchart LR
  accTitle: Die drei Musterkategorien der Gang of Four mit Beispielen
  G["Entwurfsmuster der Gang of Four"] --> E["Erzeugung: Singleton, Factory"]
  G --> V["Verhalten: Observer, Strategy, Command"]
  G --> S["Struktur: Adapter, Decorator"]

Die Kapitel 15 und 16 behandeln die Erzeugungsmuster, Kapitel 17 die Verhaltensmuster und Kapitel 18 die Strukturmuster. Die Klassendiagramme darin nutzen die Notation aus Kapitel 09 (UML). Das gemeinsame Thema der Erzeugungsmuster: Die Entscheidung, welches Objekt entsteht, wird von der Stelle getrennt, die das Objekt benutzt.

Was ein Muster von einer Bibliothek unterscheidet, zeigt der direkte Vergleich:

BibliothekEntwurfsmuster
Was ist es?fertiger Code, den du einbindesteine Beschreibung, wie man ein Problem strukturiert
Wie nutzt du es?import und aufrufenselbst implementieren und ans Problem anpassen
Sprachabhängig?janein, die Idee gilt in jeder objektorientierten Sprache
Wo steckt der Wert?im gelieferten Codein Lösung und Name

Wo begegnet dir das? Im Code-Review (“das ist doch eigentlich ein Observer”), in der Dokumentation von Frameworks und in jedem Fachgespräch zur Diplomarbeit. Auch Klassennamen wie ...Factory oder ...Builder in Bibliotheken sind oft ein Hinweis darauf, welches Muster dahintersteckt.

Auflösung

Nur (b). (a) ist die Nutzung einer Bibliothek, (c) ist Wiederverwendung von Code. Beide liefern fertigen Code. (b) beschreibt eine Struktur, die sich in jeder Sprache und für jedes Problem dieser Art umsetzen lässt, und sie hat einen Namen: Factory.

Bevor wir einzelne Muster ansehen, lohnt der Blick auf die Grundsätze, denen sie dienen. SOLID ist ein Merkwort für fünf Prinzipien objektorientierten Entwurfs. Robert C. Martin (“Uncle Bob”) fasste sie unter diesem Akronym zusammen. Es sind keine Ja/Nein-Regeln, sondern Leitlinien, die Code änderbar und testbar halten, indem sie Kopplung reduzieren und Verantwortlichkeiten klar trennen.

flowchart LR
  accTitle: Von hoher Kopplung über SOLID zu lokalen Änderungen
  P["Problem: eine Änderung zieht Kreise"] --> K["Ursache: hohe Kopplung, gemischte Zuständigkeiten"]
  K -->|Gegenmittel| S["SOLID: fünf Leitlinien"]
  S --> Z["Ergebnis: Änderungen bleiben lokal, Code bleibt testbar"]
BuchstabePrinzipKerngedanke
SSingle ResponsibilityEine Klasse hat genau einen Grund, sich zu ändern - eine Zuständigkeit, nicht drei.
OOpen-ClosedOffen für Erweiterung, geschlossen für Änderung: Neues kommt hinzu, Bestehendes bleibt unangetastet.
LLiskov SubstitutionEin Untertyp muss überall einsetzbar sein, wo sein Obertyp erwartet wird, ohne das Programm zu überraschen.
IInterface SegregationViele kleine, gezielte Schnittstellen sind besser als eine große, die ihre Nutzer zu ungenutzten Methoden zwingt.
DDependency InversionCode hängt von Abstraktionen ab, nicht von konkreten Klassen; die konkrete Wahl wird hereingereicht.

Zwei dieser Prinzipien sind dir bereits begegnet, nur ohne das Merkwort: das O bei Vererbung und Interfaces (neue Formen ohne Änderung am Bestehenden) und das L als Ersetzbarkeitsregel der Vererbung. Neu sind vor allem S, I und D.

Der Zusammenhang mit den folgenden Kapiteln ist direkt: Entwurfsmuster sind großteils Bauanleitungen, die ein oder mehrere SOLID-Prinzipien umsetzen. Die Factory in Kapitel 16 stützt das O, und die Kritik am Singleton in Kapitel 15 mündet ins D. SOLID ist die Begründung, das Muster die Form. Wer die Prinzipien kennt, kann beurteilen, ob ein Muster ein Problem wirklich löst oder nur verschiebt.

In unserem Fußballteam sieht man die Prinzipien schon: Jede Position hat eine klare Aufgabe (S), und wer eingewechselt wird, muss die Rolle seines Vorgängers wirklich ausfüllen (L). Die Kapitel 12 bis 14 zeigen jedes Prinzip an einem Beispiel mit “schlecht” und “besser”.

Genauer erklärt: Konkret heißt das: Ein Interface mit genau einer Implementierung, an dem sich absehbar nichts ändert, bringt keinen Gewinn. Es kostet aber eine zusätzliche Datei, einen zusätzlichen Sprung beim Lesen und einen Namen, den sich alle merken müssen. Erst wenn eine zweite Variante dazukommt oder die Abhängigkeit im Test ersetzt werden soll, zahlt sich die Abstraktion aus. Die Reihenfolge ist also: zuerst das Problem benennen (welche Änderung zieht Kreise?), dann das passende Prinzip wählen.

Wo begegnet dir das? Wenn in einem Code-Review jemand schreibt “diese Klasse macht zu viel” oder “das sollte ein Interface sein”, steckt fast immer eines dieser fünf Prinzipien dahinter. Auch Frameworks wie Angular oder NestJS sind um die Idee aufgebaut, Abhängigkeiten von außen hereinzureichen (das D).

Auflösung

(1) ist S: mehrere Zuständigkeiten, also mehrere Gründe, sich zu ändern. (2) ist O: Neues Verhalten sollte als neue Klasse dazukommen, nicht als neuer Zweig in bestehender Logik. (3) ist D: Die Klasse hängt von einer konkreten Klasse ab, statt eine Abstraktion hereingereicht zu bekommen. Alle drei Prinzipien siehst du in den Kapiteln 12 und 14 mit Code.

  • refactoring.guru: Design Patterns - alle klassischen Muster nach den drei Kategorien geordnet, jeweils mit Problem, Lösung und Code; gut, um die Landkarte aus diesem Kapitel vorab zu erkunden.
  • Wikipedia: Design Patterns - Hintergrund zum Buch der Gang of Four und zur Einteilung in Erzeugungs-, Struktur- und Verhaltensmuster.
  • Wikipedia: SOLID - kompakte Übersicht der fünf Prinzipien mit Verweisen auf die Originalquellen, gut zum schnellen Nachschlagen vor der Schularbeit.
  • Robert C. Martin, Agile Software Development, Principles, Patterns, and Practices bzw. Clean Architecture - die SOLID-Prinzipien in voller Tiefe vom Autor, der das Akronym geprägt hat.

Du kannst dir diesen Text mit der Vorlesefunktion deines Browsers oder Betriebssystems kostenlos anhören, etwa mit “Laut vorlesen” in Microsoft Edge. Das eignet sich gut zum Wiederholen vor der Schularbeit.

Lernergebnisse: Was du nach diesem Kapitel können solltest

Abschnitt betitelt „Lernergebnisse: Was du nach diesem Kapitel können solltest“
  • Erklären: erklären, was ein Entwurfsmuster ist, und den Nutzen von Mustern als gemeinsames Vokabular begründen.
  • Nennen: die drei Musterkategorien (Erzeugung, Verhalten, Struktur) mit Beispielen nennen und ein Entwurfsmuster von einer Bibliothek unterscheiden.
  • Nennen: die fünf SOLID-Prinzipien mit ihrem Kerngedanken in einem Satz wiedergeben und einer typischen Code-Review-Aussage zuordnen.
  • Beurteilen: begründen, warum SOLID ein Kompass für Code unter Änderungsdruck und keine Checkliste ist.
  • Aufgabe 07 - Jahresprojekt Sprint 2 - Design-Review mit SOLID: Kata: Review-Kommentare einem Muster, einer Bibliothek oder einem SOLID-Buchstaben zuordnen, dazu das Planning von Sprint 2 (Wesentlich_überwiegend); docs/design-review.md mit einem SOLID-Befund aus dem eigenen Code, einem echten Review-Kommentar und den Musterkandidaten (Wesentlich_vollständig). PlusPlus: Abstraktionsregel des Teams; MandalorianPlus: die Regel an Merge Requests prüfen.

Die Prinzipien selbst setzt du in den nächsten Wochen im Projekt um: S, O und L in Aufgabe 08, I und D in Aufgabe 09.

GAM

CC-BY-SA

https://qiz.at/rules