Menu
Coddy logo textTech

Strategy-Pattern

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 69 von 87.

Das Strategy-Pattern ist ein Verhaltensmuster, das es Ihnen ermöglicht, eine Familie von Algorithmen zu definieren, jeden einzelnen in einer eigenen Klasse zu kapseln und sie austauschbar zu machen. Anstatt ein bestimmtes Verhalten fest zu codieren, können Sie Algorithmen zur Laufzeit austauschen, ohne den Code zu ändern, der sie verwendet.

Stellen Sie sich ein Zahlungssystem vor, das mehrere Zahlungsmethoden unterstützt. Ohne das Strategy-Pattern würden Sie bei einer unübersichtlichen bedingten Logik landen. Mit diesem Pattern wird jede Zahlungsmethode zu einer 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 Context-Klasse hält eine Referenz auf eine Strategie und delegiert die Arbeit an diese. Der entscheidende Punkt ist, dass der Context nicht weiß, welche konkrete Strategie er verwendet – er kennt nur das Interface:

class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}

Jetzt können Sie das Zahlungsverhalten dynamisch ändern:

ShoppingCart cart = new ShoppingCart();

cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100);  // 100 via Kreditkarte bezahlt

cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50);   // 50 via PayPal bezahlt

Das Strategy-Pattern glänzt, wenn Sie mehrere Möglichkeiten haben, eine Aktion auszuführen, und einfach zwischen ihnen wechseln möchten. Das Hinzufügen einer neuen Zahlungsmethode bedeutet lediglich das Erstellen einer neuen Klasse, die PaymentStrategy implementiert – es sind keine Änderungen am bestehenden Code erforderlich.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Textformatierungssystem mit dem Strategy Pattern bauen! Sie werden ein System erstellen, bei dem verschiedene Formatierungsstrategien zur Laufzeit ausgetauscht werden können, um Text auf verschiedene Arten zu transformieren – perfekt für eine Anwendung, die mehrere Ausgabeformate unterstützen muss.

Sie werden Ihren Code über vier Dateien organisieren:

  • TextFormatter.java: Definieren Sie das TextFormatter-Interface, das alle Formatierungsstrategien implementieren werden. Es sollte eine einzige Methode String format(String text) deklarieren, die einen String entgegennimmt und die formatierte Version zurückgibt.
  • Formatters.java: Erstellen Sie drei konkrete Strategien, die Ihr TextFormatter-Interface implementieren:

    UpperCaseFormatter - transformiert den Text in lauter Großbuchstaben.

    LowerCaseFormatter - transformiert den Text in lauter Kleinbuchstaben.

    TitleCaseFormatter - schreibt den ersten Buchstaben jedes Wortes groß, während der Rest klein geschrieben wird. Wörter sind durch Leerzeichen getrennt.

  • TextEditor.java: Erstellen Sie die Kontextklasse, die eine Formatierungsstrategie verwendet. Ihr TextEditor sollte Folgendes haben:

    Ein privates Feld, um die aktuelle TextFormatter-Strategie zu halten.

    Eine setFormatter(TextFormatter formatter)-Methode, die die aktive Formatierungsstrategie ändert.

    Eine publishText(String text)-Methode, die den aktuellen Formatter auf den Text anwendet und Published: [formatted text] ausgibt. Wenn kein Formatter gesetzt wurde, sollte sie Published: [original text] unverändert ausgeben.

  • Main.java: Bringen Sie Ihr Strategiesystem zusammen! Sie erhalten zwei Eingaben: den zu formatierenden Text (String) und den Formatierungsstil (String: "upper", "lower" oder "title").

    Erstellen Sie einen TextEditor und rufen Sie zuerst publishText mit Ihrem Eingabetext auf, bevor Sie einen Formatter setzen (um das Standardverhalten zu demonstrieren).

    Setzen Sie dann basierend auf der Stileingabe die entsprechende Formatter-Strategie und rufen Sie publishText erneut mit demselben Text auf, um das formatierte Ergebnis anzuzeigen.

Sie erhalten nacheinander zwei Eingaben: den zu formatierenden Text (String) und den Formatierungsstil (String).

Zum Beispiel, bei den Eingaben hello world und title, wäre Ihre Ausgabe:

Published: hello world
Published: Hello World

Beachten Sie, dass der TextEditor nichts über die spezifische Formatierungslogik weiß – er delegiert einfach an die Strategie, die gerade gesetzt ist. Dies macht es trivial, neue Formatierungsstile hinzuzufügen, ohne den Code des Editors anzupassen!

Spickzettel

Das Strategy Pattern (Strategiemuster) ist ein Verhaltensmuster, das eine Familie von Algorithmen definiert, jeden einzelnen in einer eigenen Klasse kapselt und sie austauschbar macht. Es ermöglicht den Austausch von Algorithmen zur Laufzeit, ohne den Code zu ändern, der sie verwendet.

Schlüsselkomponenten

Strategy Interface: Definiert die gemeinsame Schnittstelle für alle konkreten Strategien.

interface PaymentStrategy {
    void pay(int amount);
}

Konkrete Strategien: Implementieren das Strategy Interface mit spezifischen Algorithmen.

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");
    }
}

Kontext-Klasse: Hält eine Referenz auf eine Strategie und delegiert die Arbeit an diese. Der Kontext kennt nur das Interface, nicht die konkrete Implementierung.

class ShoppingCart {
    private PaymentStrategy paymentStrategy;
    
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.paymentStrategy = strategy;
    }
    
    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}

Verwendung

Strategien können zur Laufzeit dynamisch geändert werden:

ShoppingCart cart = new ShoppingCart();

cart.setPaymentStrategy(new CreditCardPayment());
cart.checkout(100);  // Paid 100 via Credit Card

cart.setPaymentStrategy(new PayPalPayment());
cart.checkout(50);   // Paid 50 via PayPal

Vorteile

Das Strategy Pattern ist ideal, wenn Sie mehrere Möglichkeiten haben, eine Aktion auszuführen, und einfach zwischen ihnen wechseln möchten. Das Hinzufügen einer neuen Strategie bedeutet lediglich das Erstellen einer neuen Klasse, die das Strategy Interface implementiert – es sind keine Änderungen am bestehenden Code erforderlich.

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: Erstellen Sie eine TextEditor-Instanz
        
        // TODO: Rufen Sie publishText mit dem Eingabetext auf (bevor ein Formatter gesetzt wird)
        
        // TODO: Basierend auf der Style-Eingabe ("upper", "lower" oder "title"),
        // setzen Sie den entsprechenden Formatter und rufen Sie publishText erneut auf
        
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung