Wzorzec Strategy
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 93 z 110.
Wzorzec Strategy pozwala zdefiniować rodzinę algorytmów, zamknąć każdy z nich we własnej klasie i sprawić, by można je było wymieniać w czasie działania programu. Zamiast kodować zachowanie na stałe w klasie, wstrzykujesz je za pośrednictwem interfejsu, co pozwala wymieniać strategie bez modyfikowania klasy, która z nich korzysta.
Rozważ system płatności, w którym chcesz obsługiwać różne metody płatności. Zamiast używać instrukcji warunkowych do obsługi każdej metody, definiujesz interfejs strategii i tworzysz konkretne implementacje:
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); // Zapłacono $99.99 kartą kredytową
cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99); // Zapłacono $49.99 przez PayPal
}Obiekt ShoppingCart nie wie, jak działa płatność, i nie obchodzi go to — po prostu deleguje jej obsługę do aktualnie ustawionej strategii. Możesz dodawać nowe metody płatności, tworząc nowe klasy strategii, bez modyfikowania kodu koszyka. Ten wzorzec sprawdza się idealnie, gdy masz kilka sposobów wykonania działania i chcesz dynamicznie wybierać między nimi lub przełączać się między nimi.
Wyzwanie
ŁatwyZbudujmy system formatowania tekstu z użyciem wzorca Strategia! Stworzysz system, w którym do tekstu można stosować różne strategie formatowania, umożliwiając użytkownikom dynamiczne przełączanie formatów bez zmieniania głównego procesora tekstu.
Podzielisz kod na dwa pliki:
formatting_strategies.dart: Tutaj utwórz system strategii. Zdefiniuj klasę abstrakcyjnąFormattingStrategyz metodąString format(String text). Następnie zaimplementuj trzy konkretne strategie:UppercaseStrategy- zamienia cały tekst na wielkie literyLowercaseStrategy- zamienia cały tekst na małe literyTitleCaseStrategy- zamienia pierwszą literę każdego słowa na wielką (podziel tekst według spacji, zamień pierwszy znak każdego słowa na wielką literę, a pozostałe na małe)
TextProcessor, która przechowujeFormattingStrategy. Powinna mieć konstruktor przyjmujący początkową strategię, metodęsetStrategy()do zmiany strategii w czasie działania programu oraz metodęprocess(String text), która stosuje bieżącą strategię i zwraca sformatowany wynik.main.dart: Zaimportuj strategie formatowania i pokaż, jak wzorzec Strategia umożliwia dynamiczne przełączanie zachowania. UtwórzTextProcessor, zaczynając odUppercaseStrategy. Przetwórz teksthello worldi wyświetl wynik. Następnie przełącz naLowercaseStrategy, przetwórzHELLO WORLDi wyświetl wynik. Na koniec przełącz naTitleCaseStrategy, przetwórzthe quick brown foxi wyświetl wynik.
To pokazuje siłę wzorca Strategia — TextProcessor nie musi znać szczegółów działania formatowania. Po prostu przekazuje zadanie aktualnie ustawionej strategii, dzięki czemu można łatwo dodawać nowe opcje formatowania bez modyfikowania procesora!
Oczekiwany wynik:
HELLO WORLD
hello world
The Quick Brown FoxSpróbuj swoich sił
import 'formatting_strategies.dart';
void main() {
// TODO: Utwórz TextProcessor, zaczynając od UppercaseStrategy
// TODO: Przetwórz tekst 'hello world' i wypisz wynik
// TODO: Przełącz na LowercaseStrategy
// TODO: Przetwórz 'HELLO WORLD' i wypisz wynik
// TODO: Przełącz na TitleCaseStrategy
// TODO: Przetwórz 'the quick brown fox' i wypisz wynik
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online