Menu
Coddy logo textTech

Strategy-Muster

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 93 von 110.

Das Strategy-Pattern ermöglicht es Ihnen, eine Familie von Algorithmen zu definieren, jeden einzelnen in einer eigenen Klasse zu kapseln und sie zur Laufzeit austauschbar zu machen. Anstatt das Verhalten fest in eine Klasse zu kodieren, injizieren Sie das Verhalten über eine Schnittstelle, was es Ihnen ermöglicht, Strategien auszutauschen, ohne die Klasse, die sie verwendet, zu ändern.

Stellen Sie sich ein Zahlungssystem vor, bei dem Sie verschiedene Zahlungsmethoden unterstützen möchten. Anstatt Bedingungen zu verwenden, um jede Methode zu handhaben, definieren Sie eine Strategie-Schnittstelle und erstellen konkrete Implementierungen:

abstract class PaymentStrategy {
  void pay(double amount);
}

class CreditCardPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$amount with Credit Card');
}

class PayPalPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$amount with PayPal');
}

class ShoppingCart {
  PaymentStrategy _paymentStrategy;

  ShoppingCart(this._paymentStrategy);

  void setPaymentStrategy(PaymentStrategy strategy) {
    _paymentStrategy = strategy;
  }

  void checkout(double total) {
    _paymentStrategy.pay(total);
  }
}

void main() {
  var cart = ShoppingCart(CreditCardPayment());
  cart.checkout(99.99);  // 99.99 $ mit Kreditkarte bezahlt

  cart.setPaymentStrategy(PayPalPayment());
  cart.checkout(49.99);  // 49.99 $ mit PayPal bezahlt
}

Der ShoppingCart weiß nicht und es ist ihm egal, wie die Zahlung funktioniert – er delegiert einfach an die Strategie, die aktuell eingestellt ist. Sie können neue Zahlungsmethoden hinzufügen, indem Sie neue Strategie-Klassen erstellen, ohne den Code des Warenkorbs anzupassen. Dieses Muster ist ideal, wenn Sie mehrere Möglichkeiten haben, eine Aktion auszuführen, und dynamisch zwischen ihnen wählen oder wechseln möchten.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Textformatierungssystem mit dem Strategy-Pattern erstellen! Sie werden ein System entwickeln, bei dem verschiedene Formatierungsstrategien auf Text angewendet werden können, sodass Benutzer dynamisch zwischen Formaten wechseln können, ohne den Kern des Textprozessors zu ändern.

Sie werden Ihren Code in zwei Dateien organisieren:

  • formatting_strategies.dart: Erstellen Sie hier Ihr Strategiesystem. Definieren Sie eine abstrakte Klasse FormattingStrategy mit einer Methode String format(String text). Implementieren Sie dann drei konkrete Strategien:
    • UppercaseStrategy - wandelt Text in Großbuchstaben um
    • LowercaseStrategy - wandelt Text in Kleinbuchstaben um
    • TitleCaseStrategy - schreibt den ersten Buchstaben jedes Wortes groß (nach Leerzeichen trennen, das erste Zeichen jedes Wortes großschreiben, den Rest klein)
    Erstellen Sie außerdem eine TextProcessor-Klasse, die eine FormattingStrategy hält. Sie sollte einen Konstruktor haben, der eine initiale Strategie akzeptiert, eine setStrategy()-Methode, um die Strategie zur Laufzeit zu ändern, und eine process(String text)-Methode, die die aktuelle Strategie anwendet und das formatierte Ergebnis zurückgibt.
  • main.dart: Importieren Sie Ihre Formatierungsstrategien und demonstrieren Sie, wie das Strategy-Pattern den dynamischen Wechsel des Verhaltens ermöglicht. Erstellen Sie einen TextProcessor, der mit der UppercaseStrategy beginnt. Verarbeiten Sie den Text 'hello world' und geben Sie das Ergebnis aus. Wechseln Sie dann zur LowercaseStrategy, verarbeiten Sie 'HELLO WORLD' und geben Sie das Ergebnis aus. Wechseln Sie schließlich zur TitleCaseStrategy, verarbeiten Sie 'the quick brown fox' und geben Sie das Ergebnis aus.

Dies demonstriert die Stärke des Strategy-Patterns – Ihr TextProcessor muss die Details der Formatierung nicht kennen. Er delegiert einfach an die aktuell eingestellte Strategie, was es einfach macht, neue Formatierungsoptionen hinzuzufügen, ohne den Prozessor zu modifizieren!

Erwartete Ausgabe:

HELLO WORLD
hello world
The Quick Brown Fox

Spickzettel

Das Strategy-Muster definiert eine Familie von Algorithmen, kapselt jeden einzelnen in einer eigenen Klasse und macht sie zur Laufzeit austauschbar. Anstatt das Verhalten fest zu kodieren, injizieren Sie es über eine Schnittstelle.

Definieren Sie ein Strategy-Interface:

abstract class PaymentStrategy {
  void pay(double amount);
}

Erstellen Sie konkrete Strategy-Implementierungen:

class CreditCardPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$amount with Credit Card');
}

class PayPalPayment implements PaymentStrategy {
  @override
  void pay(double amount) => print('Paid \$amount with PayPal');
}

Erstellen Sie eine Kontext-Klasse, die die Strategy verwendet:

class ShoppingCart {
  PaymentStrategy _paymentStrategy;

  ShoppingCart(this._paymentStrategy);

  void setPaymentStrategy(PaymentStrategy strategy) {
    _paymentStrategy = strategy;
  }

  void checkout(double total) {
    _paymentStrategy.pay(total);
  }
}

Verwenden Sie das Muster, indem Sie Strategien injizieren und wechseln:

var cart = ShoppingCart(CreditCardPayment());
cart.checkout(99.99);  // Bezahlt $99.99 mit Kreditkarte

cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99);  // Bezahlt $49.99 mit PayPal

Die Kontext-Klasse delegiert das Verhalten an die Strategy, ohne Implementierungsdetails zu kennen. Fügen Sie neue Strategien hinzu, indem Sie neue Klassen erstellen, ohne bestehenden Code zu ändern.

Probier es selbst

import 'formatting_strategies.dart';

void main() {
  // TODO: Erstelle einen TextProcessor, der mit UppercaseStrategy beginnt
  
  // TODO: Verarbeite den Text 'hello world' und gib das Ergebnis aus
  
  // TODO: Wechsle zu LowercaseStrategy
  
  // TODO: Verarbeite 'HELLO WORLD' und gib das Ergebnis aus
  
  // TODO: Wechsle zu TitleCaseStrategy
  
  // TODO: Verarbeite 'the quick brown fox' und gib das Ergebnis aus
}
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