Strategiemuster
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 93 von 110.
Das Strategy pattern ermöglicht es dir, eine Familie von Algorithmen zu definieren, jeden einzelnen in einer eigenen Klasse zu kapseln und sie zur Laufzeit austauschbar zu machen. Anstatt das Verhalten in einer Klasse fest zu codieren, injizierst du das Verhalten über ein Interface, sodass du Strategien austauschen kannst, ohne die Klasse zu ändern, die sie verwendet.
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.
Aufgabe
EinfachErstellen wir ein Textformatierungssystem mit dem Strategy-Muster! Du erstellst ein System, in dem verschiedene Formatierungsstrategien auf Text angewendet werden können, sodass Benutzer dynamisch zwischen Formaten wechseln können, ohne den zentralen Textprozessor zu ändern.
Du organisierst deinen Code in zwei Dateien:
formatting_strategies.dart: Erstelle hier dein Strategiesystem. Definiere eine abstrakte KlasseFormattingStrategymit einer MethodeString format(String text). Implementiere anschließend drei konkrete Strategien:UppercaseStrategy– wandelt den Text in Großbuchstaben umLowercaseStrategy– wandelt den Text in Kleinbuchstaben umTitleCaseStrategy– schreibt den ersten Buchstaben jedes Wortes groß (nach Leerzeichen aufteilen, das erste Zeichen jedes Wortes großschreiben, den Rest kleinschreiben)
TextProcessor, die eineFormattingStrategyenthält. Sie sollte einen Konstruktor haben, der eine anfängliche Strategie akzeptiert, einesetStrategy()-Methode zum Ändern der Strategie zur Laufzeit und eineprocess(String text)-Methode, die die aktuelle Strategie anwendet und das formatierte Ergebnis zurückgibt.main.dart: Importiere deine Formatierungsstrategien und demonstriere, wie das Strategy-Muster einen dynamischen Verhaltenswechsel ermöglicht. Erstelle einenTextProcessor, der mit derUppercaseStrategybeginnt. Verarbeite den Texthello worldund gib das Ergebnis aus. Wechsle dann zuLowercaseStrategy, verarbeiteHELLO WORLDund gib das Ergebnis aus. Wechsle schließlich zuTitleCaseStrategy, verarbeitethe quick brown foxund gib das Ergebnis aus.
Dies demonstriert die Leistungsfähigkeit des Strategy-Musters – dein TextProcessor muss die Details der Formatierung nicht kennen. Er delegiert einfach an die aktuell gesetzte Strategie, wodurch sich neue Formatierungsoptionen problemlos hinzufügen lassen, ohne den Prozessor zu ändern!
Erwartete Ausgabe:
HELLO WORLD
hello world
The Quick Brown FoxProbier 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
}
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 DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler