Alle Tabs der Lerneinheit (Erklärung · Interaktiv verstehen · Praxis-Übung · Klausur-Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
Diese Lerneinheit wurde für typische Bachelor-Klausuren konzipiert. So prüfen wir · Fehler entdeckt? Melde ihn uns oder markiere die fragliche Stelle direkt im Text oben.
Alle Tabs der Lerneinheit (Erklärung · Interaktiv verstehen · Praxis-Übung · Klausur-Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).
1994 — Gamma, Helm, Johnson, Vlissides ("Gang of Four") veröffentlichen 23 Entwurfsmuster für objektorientierte Software. Bis heute Pflicht in jeder SE-Klausur.
Klausur-Tipp: In der Klausur wird oft ein Code-Beispiel gezeigt und die Frage gestellt: "Welches Pattern liegt vor?". Indikatoren: privater Konstruktor + getInstance() = Singleton. Methode gibt Interface zurück basierend auf Parameter = Factory. Klasse mit Liste von Listenern + notify() = Observer. Interface + austauschbare Implementierungen = Strategy.
Anmelden, um den Fortschritt zu speichern.
Nächster Schritt
Aktives Abrufen festigt Wissen schneller als nochmal lesen.
1994 — Gamma, Helm, Johnson, Vlissides ("Gang of Four") veröffentlichen 23 Entwurfsmuster für objektorientierte Software. Bis heute Pflicht in jeder SE-Klausur.
Entwurfsmuster: Bewährte Lösung für ein wiederkehrendes Entwurfs-Problem in einem bestimmten Kontext.
Stell dir vor, du baust Software ohne sie:
new ConcreteClass() zu schreiben?"Diese Probleme tauchen IMMER WIEDER auf. Muster sind die kondensierten Lösungen aus 50 Jahren OOP-Erfahrung.
| Kategorie | Zweck | Beispiele |
|---|---|---|
| Erzeugungsmuster (Creational) | Wie werden Objekte erzeugt? | Singleton, Factory, Builder, Prototype |
| Strukturmuster (Structural) | Wie sind Klassen/Objekte zusammengesetzt? | Adapter, Decorator, Facade, Composite |
| Verhaltensmuster (Behavioral) | Wie kommunizieren Objekte? | Observer, Strategy, Command, Iterator |
Problem: Es soll nur EINE Instanz einer Klasse geben (z.B. Logger, DB-Connection, Config).
public class Logger {
private static Logger instance;
private Logger() {} // private! niemand kann new Logger() machen
public static Logger getInstance() {
if (instance == null) {
instance = new Logger();
}
return instance;
}
public void log(String msg) {
System.out.println("[LOG] " + msg);
}
}
// Verwendung:
Logger.getInstance().log("Hallo");
Logger.getInstance().log("Welt");
// Beide Aufrufe nutzen DIESELBE Instanz!
Vorteile: Globaler Zugriff, kontrollierter Lifecycle. Nachteile: "Globale Variable in OOP-Verkleidung", schwer zu testen, oft Anti-Pattern.
Problem: Objekt-Erzeugung soll von der KONKRETEN Klasse entkoppelt werden.
// Ohne Factory:
Tier tier = new Hund(); // Code kennt Hund-Klasse
Tier tier2 = new Katze();
// Mit Factory:
interface Tier {
void laut();
}
class Hund implements Tier { public void laut() { System.out.println("Wuff!"); } }
class Katze implements Tier { public void laut() { System.out.println("Miau!"); } }
class TierFactory {
public static Tier erzeuge(String typ) {
return switch (typ) {
case "hund" -> new Hund();
case "katze" -> new Katze();
default -> throw new IllegalArgumentException();
};
}
}
// Verwendung:
Tier tier = TierFactory.erzeuge("hund");
tier.laut(); // Wuff!
// Code kennt nur das Interface Tier — nicht die konkrete Klasse!
Vorteil: Lose Kopplung, einfacher zu erweitern.
Problem: Wenn sich ein Objekt ändert, sollen mehrere andere Objekte benachrichtigt werden.
interface Observer {
void update(String event);
}
class NewsAgentur {
private List<Observer> abonnenten = new ArrayList<>();
public void abonniere(Observer o) {
abonnenten.add(o);
}
public void publish(String news) {
for (Observer o : abonnenten) {
o.update(news); // alle benachrichtigen
}
}
}
class EmailNotifier implements Observer {
public void update(String e) { System.out.println("EMAIL: " + e); }
}
class PushNotifier implements Observer {
public void update(String e) { System.out.println("PUSH: " + e); }
}
// Verwendung:
NewsAgentur agentur = new NewsAgentur();
agentur.abonniere(new EmailNotifier());
agentur.abonniere(new PushNotifier());
agentur.publish("Eilmeldung!");
// Beide Notifier werden informiert!
Vorteil: Lose Kopplung zwischen Subject und Observer. Klassiker: UI-Frameworks (React, Vue), Event-Listeners, Pub-Sub-Systeme.
Problem: Verschiedene Algorithmen sollen austauschbar sein.
interface SortStrategy {
void sort(int[] arr);
}
class BubbleSortStrategy implements SortStrategy {
public void sort(int[] arr) { /* Bubblesort */ }
}
class QuicksortStrategy implements SortStrategy {
public void sort(int[] arr) { /* Quicksort */ }
}
class Sortierer {
private SortStrategy strategy;
public Sortierer(SortStrategy s) {
this.strategy = s;
}
public void sortiere(int[] arr) {
strategy.sort(arr);
}
}
// Verwendung:
Sortierer s1 = new Sortierer(new BubbleSortStrategy());
Sortierer s2 = new Sortierer(new QuicksortStrategy());
// Verhalten ändert sich, nicht die Klasse!
Vorteil: Algorithmus zur Laufzeit austauschbar, Open/Closed-Prinzip.
| Pattern | Kategorie | Zweck |
|---|---|---|
| Builder | Erzeugung | Komplexe Objekt-Konstruktion in Schritten |
| Adapter | Struktur | Inkompatible Interfaces verbinden |
| Decorator | Struktur | Verhalten dynamisch hinzufügen |
| Facade | Struktur | Vereinfachtes Interface für komplexes Subsystem |
| Iterator | Verhalten | Sequenzieller Zugriff auf Collection-Elemente |
| Command | Verhalten | Aktion als Objekt kapseln (Undo/Redo!) |
| State | Verhalten | Verhalten ändert sich basierend auf internem Zustand |
| Buchstabe | Prinzip |
|---|---|
| Single Responsibility | Eine Klasse — eine Aufgabe |
| Open/Closed | Offen für Erweiterung, geschlossen für Änderung |
| Liskov Substitution | Subklassen müssen Superklassen ersetzen können |
| Interface Segregation | Viele kleine Interfaces > ein großes |
| Dependency Inversion | Abhängigkeiten auf Abstraktionen, nicht Implementierungen |
1. 3 Kategorien: Creational (Erzeugung), Structural (Struktur), Behavioral (Verhalten).
2. Singleton: EINE Instanz. Private Konstruktor, statische getInstance().
3. Factory: Erzeugt Objekte ohne neue\ KonkreteKlasse() aufzurufen — gibt nur das Interface zurück.
4. Observer: Subject + Observer. Subject ruft observer.update() bei Änderung.
5. Strategy: Algorithmus als Interface, konkrete Implementierungen austauschbar.
6. Pattern ≠ Bibliothek. Pattern ist eine Lösungs-Schablone, kein fertiger Code.
1. Singleton überall nutzen. FALSCH. Singleton ist ein Anti-Pattern, wenn du es als globale Variable missbrauchst. Nur dort, wo wirklich nur EINE Instanz Sinn macht (Logger, Config).
2. Factory mit Builder verwechseln. Factory erzeugt EIN Objekt mit einer Methode. Builder konstruiert ein KOMPLEXES Objekt in mehreren Schritten ("schritt1.schritt2.schritt3.build()").
3. Observer = Pub-Sub. Stimmt zur Hälfte. Beim klassischen Observer kennt das Subject seine Observer (Liste). Bei Pub-Sub gibt es einen Broker dazwischen — Subject und Subscriber kennen sich NICHT direkt.
4. Patterns sind Pflicht. FALSCH. Wenn du keine Wiederverwendbarkeit/Erweiterbarkeit brauchst, ist ein Pattern nur Overhead. "YAGNI" (You Ain't Gonna Need It) gilt auch hier.
5. Strategy mit State verwechseln. Strategy = Algorithmus austauschen (z.B. Sortier-Algo). State = Verhalten basiert auf internem Zustand (z.B. Ampel-Zustand).
Wähle ein Pattern und sieh, wie es funktioniert. Pro Pattern: Problem, UML-Skizze, Code-Schritte, Verwendungs-Beispiel.
Interaktive Visualisierung
Interaktive Komponente: probiere sie im Topic-Player oben aus.
Klausur-Tipp: In der Klausur wird oft ein Code-Beispiel gezeigt und die Frage gestellt: "Welches Pattern liegt vor?". Indikatoren: privater Konstruktor + getInstance() = Singleton. Methode gibt Interface zurück basierend auf Parameter = Factory. Klasse mit Liste von Listenern + notify() = Observer. Interface + austauschbare Implementierungen = Strategy.
6 Aufgaben zu Klassifikation, Anwendungsbereichen und Code-Beispielen.
Klausurfragen mit Lösungen (6)
Antwort: Singleton und Factory
Erklärung: Singleton und Factory sind beides Erzeugungsmuster (Creational): sie kümmern sich darum, WIE Objekte erstellt werden. Observer/Strategy sind Verhaltensmuster (Behavioral), Adapter/Decorator sind Strukturmuster (Structural), Iterator/Command auch Verhaltensmuster.
Antwort: Es gibt nur EINE Instanz einer Klasse, globaler Zugriff
Erklärung: Singleton garantiert: nur EINE Instanz, globaler Zugriffspunkt. Implementiert mit privatem Konstruktor + statischer Instance-Variable + statischer getInstance()-Methode. Wichtig in Klausur: zwei Bedingungen — (1) nur eine Instanz, (2) globaler Zugriff. Beides muss zutreffen.
Zuordnungen:
Erklärung: GoF teilt 23 Patterns in 3 Kategorien: Creational (Singleton, Factory, Builder, Prototype, Abstract Factory), Structural (Adapter, Decorator, Facade, Composite, Bridge, Proxy, Flyweight), Behavioral (Observer, Strategy, Command, Iterator, State, Template Method, Visitor, Chain of Responsibility, Mediator, Memento, Interpreter).
Typ: Zuordnung
Antwort: Observer
Erklärung: Observer ist das Pattern hinter Reactive-Frameworks: ein State (Subject) hat Observer (Komponenten), die bei Änderung benachrichtigt werden und neu rendern. React useState + useEffect, Vue ref + watch, RxJS Observables — alles Observer-basiert. Pub-Sub-Systeme (Kafka, Redis Pub/Sub) basieren ebenfalls auf Observer-Idee.
Antwort:
Erklärung: Der Konstruktor MUSS `private` sein, damit nicht von außen `new Logger()` aufgerufen werden kann. Dadurch ist die einzige Möglichkeit, eine Logger-Instanz zu bekommen, der Aufruf `Logger.getInstance()`. Das ist die Schlüssel-Mechanik des Singleton-Patterns.
Typ: Code ergänzen
Antwort: Wahr
Erklärung: RICHTIG. Strategy und State haben strukturell den gleichen Aufbau: Context-Klasse hält Referenz auf ein Interface, das verschiedene Implementierungen hat. ABER der Zweck unterscheidet sich: Strategy = AUSTAUSCHBARE ALGORITHMEN (Sortier-Algorithmen, Bezahl-Methoden). State = VERHALTEN basiert auf INTERNEM ZUSTAND (Ampel rot/gelb/grün, Bestellung neu/bezahlt/versendet). Klausur-Klassiker.
Typ: Wahr/Falsch
6 typische Klausurfragen.
Klausurfragen mit Lösungen (6)
Antwort: Gang of Four: Gamma, Helm, Johnson, Vlissides
Erklärung: Die 'Gang of Four' (GoF) — Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides — veröffentlichten 1994 das Standardwerk 'Design Patterns: Elements of Reusable Object-Oriented Software' mit 23 Mustern. Uncle Bob (Robert C. Martin) ist für SOLID-Prinzipien und Clean Code bekannt, nicht für GoF.
Antwort: Adapter
Erklärung: Adapter ist ein STRUKTURMUSTER — es verbindet zwei inkompatible Interfaces (z.B. ein altes API mit einem neuen). Erzeugungsmuster sind: Singleton, Factory, Abstract Factory, Builder, Prototype — alle kümmern sich darum, WIE Objekte erstellt werden, nicht wie sie verknüpft sind.
Lösungen pro Lücke:
Erklärung: Singleton: privater Konstruktor verhindert direkten `new`-Aufruf, getInstance() ist die statische Methode für den Zugriff. SOLID = Single Responsibility, Open/Closed, Liskov Substitution (Subklassen müssen Superklassen ersetzen können), Interface Segregation, Dependency Inversion. Klausur-Klassiker.
Typ: Lückentext
Richtige Reihenfolge:
Erklärung: Observer-Ablauf: 1) Observer registriert sich beim Subject, 2) Subject ändert irgendwann seinen Zustand, 3) Subject benachrichtigt alle Observer per notify/update, 4) Observer reagieren (z.B. UI neu rendern). Wichtig: Subject hat Liste von Observern, Observer kennen Subject nicht zwingend.
Typ: Reihenfolge
Antwort: Strategy — verschiedene Algorithmen austauschbar machen
Erklärung: Strategy ist hier perfekt: alle Bezahl-Methoden haben dieselbe Schnittstelle (z.B. `bezahle(double betrag)`), aber unterschiedliche Implementierung. Der Code, der bezahlt, ruft nur `strategy.bezahle(100)` auf — die KONKRETE Bezahl-Methode ist austauschbar. Klassisches Strategy. Factory wäre nur die ERZEUGUNG, Strategy ist die LAUFZEIT-Austauschbarkeit.
Antwort: Wahr
Erklärung: RICHTIG. Singleton ist Pattern UND Anti-Pattern zugleich: Pattern, wenn es wirklich nur EINE Instanz geben soll (Logger, Config). Anti-Pattern, wenn es als globale Variable missbraucht wird — dann ist es schwer testbar (Mocking schwer), erzeugt versteckte Abhängigkeiten und verletzt Single-Responsibility (die Klasse macht ihre Aufgabe + verwaltet ihre Lifecycle). Modern bevorzugt: Dependency Injection statt Singleton.
Typ: Wahr/Falsch