Strategie-Muster
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 69 von 87.
Das Strategy Pattern ist ein Verhaltensentwurfsmuster, mit dem du eine Familie von Algorithmen definieren, jeden einzelnen in seiner eigenen Klasse kapseln und sie austauschbar machen kannst. Anstatt ein bestimmtes Verhalten fest zu codieren, kannst du Algorithmen zur Laufzeit austauschen, ohne den Code zu ändern, der sie verwendet.
Stell dir ein Zahlungssystem vor, das mehrere Zahlungsmethoden unterstützt. Ohne das Strategy Pattern würdest du bei einer unübersichtlichen bedingten Logik landen. Damit wird jede Zahlungsmethode zu ihrer eigenen Strategie:
interface PaymentStrategy {
void pay(int amount);
}
class CreditCardPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via Credit Card");
}
}
class PayPalPayment implements PaymentStrategy {
public void pay(int amount) {
System.out.println("Paid " + amount + " via PayPal");
}
}Die Kontext-Klasse enthält eine Referenz auf eine Strategie und delegiert die Arbeit an sie. Entscheidend ist, dass der Kontext nicht weiß, welche konkrete Strategie er verwendet. Er kennt nur die Schnittstelle:
class ShoppingCart {
private PaymentStrategy paymentStrategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.paymentStrategy = strategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}Jetzt kannst du das Zahlungsverhalten dynamisch ändern:
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100); // Bezahlt 100 via Kreditkarte
cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50); // Bezahlt 50 via PayPalDas Strategiemuster glänzt, wenn du mehrere Möglichkeiten hast, eine Aktion auszuführen, und problemlos zwischen ihnen wechseln möchtest. Eine neue Zahlungsmethode hinzuzufügen bedeutet einfach, eine neue Klasse zu erstellen, die PaymentStrategy implementiert: Es sind keine Änderungen am bestehenden Code erforderlich.
Aufgabe
EinfachErstellen wir ein Textformatierungssystem mit dem Strategy Pattern! Du erstellst ein System, in dem verschiedene Formatierungsstrategien zur Laufzeit ausgetauscht werden können, um Text auf unterschiedliche Weise umzuwandeln – perfekt für eine Anwendung, die mehrere Ausgabeformate unterstützen muss.
Du organisierst deinen Code über vier Dateien:
TextFormatter.java: Definiere dieTextFormatter-Schnittstelle, die alle Formatierungsstrategien implementieren werden. Sie sollte eine einzelne MethodeString format(String text)deklarieren, die einen String entgegennimmt und die formatierte Version zurückgibt.Formatters.java: Erstelle drei konkrete Strategien, die deineTextFormatter-Schnittstelle implementieren:UpperCaseFormatter– wandelt den Text in Großbuchstaben um.LowerCaseFormatter– wandelt den Text in Kleinbuchstaben um.TitleCaseFormatter– schreibt den ersten Buchstaben jedes Wortes groß und den Rest klein. Wörter werden durch Leerzeichen getrennt.TextEditor.java: Erstelle die Kontextklasse, die eine Formatierungsstrategie verwendet. DeinTextEditorsollte Folgendes enthalten:Ein privates Feld, das die aktuelle
TextFormatter-Strategie enthält.Eine Methode
setFormatter(TextFormatter formatter), die die aktive Formatierungsstrategie ändert.Eine Methode
publishText(String text), die den aktuellen Formatter auf den Text anwendet undPublished: [formatted text]ausgibt. Wenn kein Formatter gesetzt wurde, sollte sie unverändertPublished: [original text]ausgeben.Main.java: Führe dein Strategiesystem zusammen! Du erhältst zwei Eingaben: den zu formatierenden Text (String) und den Formatierungsstil (String:"upper","lower"oder"title").Erstelle einen
TextEditorund rufe zuerstpublishTextmit deinem Eingabetext auf, bevor du einen Formatter setzt (um das Standardverhalten zu veranschaulichen).Setze dann abhängig von der Stileingabe die passende Formatierungsstrategie und rufe
publishTexterneut mit demselben Text auf, um das formatierte Ergebnis anzuzeigen.
Du erhältst zwei Eingaben in dieser Reihenfolge: den zu formatierenden Text (String) und den Formatierungsstil (String).
Bei den Eingaben hello world und title würde deine Ausgabe beispielsweise so aussehen:
Published: hello world
Published: Hello WorldBeachte, dass der TextEditor nichts über die spezifische Formatierungslogik weiß. Er delegiert einfach an die Strategie, die aktuell gesetzt ist. Dadurch ist es äußerst einfach, neue Formatierungsstile hinzuzufügen, ohne den Editorcode ändern zu müssen!
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String text = scanner.nextLine();
String style = scanner.nextLine();
// TODO: Erstelle eine TextEditor-Instanz
// TODO: Rufe publishText mit dem Eingabetext auf (bevor ein Formatter gesetzt wird)
// TODO: Basierend auf der Style-Eingabe ("upper", "lower" oder "title"),
// setze den entsprechenden Formatter und rufe publishText erneut auf
}
}Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenFelder (Attribute)KonstruktormethodeÜberladen von KonstruktorenRückblick – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbung (extends)Das Schlüsselwort superÜberschreiben von Methoden (@Override)KonstruktorverkettungDie Object-KlasseEinfach- und mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenRückblick – Mitarbeiterhierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-SchnittstelleRückblick – Benutzerdefinierte Sortierung2Zugriffsmodifikatoren & Kapselung
Übersicht der ZugriffsebenenGetter- und Setter-MethodenInformationsverbergungDas Schlüsselwort finalRückblick – Bankkontoverwaltung5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, verschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Versiegelte Klassen (Java 17+)11Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBuilder-MusterObserver-MusterStrategie-Muster14Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungsdienst3Klassen-Props & statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Wiederholung – Counter & Utility6Schnittstellen & abstrakte Klassen
Einführung in InterfacesInterfaces implementierenMehrere Interfaces implementierenDefault & Static in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesRückblick – ZahlungssystemÜbe selbstständig: Online-Java-Compiler