Strategy
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 93 di 110.
Il pattern Strategy ti permette di definire una famiglia di algoritmi, incapsulare ciascuno nella propria classe e renderli intercambiabili durante l'esecuzione. Invece di codificare direttamente il comportamento in una classe, lo inietti tramite un'interfaccia, potendo così sostituire le strategie senza modificare la classe che le utilizza.
Considera un sistema di pagamento in cui vuoi supportare diversi metodi di pagamento. Invece di usare condizioni per gestire ogni metodo, definisci un'interfaccia strategia e crea implementazioni concrete:
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); // Pagato $99.99 con carta di credito
cart.setPaymentStrategy(PayPalPayment());
cart.checkout(49.99); // Pagato $49.99 con PayPal
}ShoppingCart non sa né gli importa come funziona il pagamento: delega semplicemente alla strategia attualmente impostata. Puoi aggiungere nuovi metodi di pagamento creando nuove classi strategia senza modificare il codice del carrello. Questo schema è ideale quando hai diversi modi per eseguire un’azione e vuoi selezionare o alternare tra essi dinamicamente.
Sfida
FacileCostruiamo un sistema di formattazione del testo usando il pattern Strategy! Creerai un sistema in cui è possibile applicare diverse strategie di formattazione al testo, consentendo agli utenti di passare dinamicamente da un formato all'altro senza modificare il processore di testo principale.
Organizzerai il codice in due file:
formatting_strategies.dart: crea qui il tuo sistema di strategie. Definisci una classe astrattaFormattingStrategycon un metodoString format(String text). Poi implementa tre strategie concrete:UppercaseStrategy- converte il testo tutto in maiuscoloLowercaseStrategy- converte il testo tutto in minuscoloTitleCaseStrategy- mette in maiuscolo la prima lettera di ogni parola (suddividi in base agli spazi, metti in maiuscolo il primo carattere di ogni parola e lascia il resto in minuscolo)
TextProcessorche contiene unaFormattingStrategy. Dovrebbe avere un costruttore che accetta una strategia iniziale, un metodosetStrategy()per cambiare la strategia durante l'esecuzione e un metodoprocess(String text)che applica la strategia corrente e restituisce il risultato formattato.main.dart: importa le tue strategie di formattazione e dimostra come il pattern Strategy consenta di cambiare dinamicamente il comportamento. Crea unTextProcessorche inizi conUppercaseStrategy. Elabora il testohello worlde stampa il risultato. Poi passa aLowercaseStrategy, elaboraHELLO WORLDe stampa il risultato. Infine, passa aTitleCaseStrategy, elaborathe quick brown foxe stampa il risultato.
Questo dimostra la potenza del pattern Strategy: il tuo TextProcessor non deve conoscere i dettagli di come funziona la formattazione. Si limita a delegare alla strategia impostata al momento, rendendo semplice aggiungere nuove opzioni di formattazione senza modificare il processore!
Output previsto:
HELLO WORLD
hello world
The Quick Brown FoxProvalo tu
import 'formatting_strategies.dart';
void main() {
// TODO: Crea un TextProcessor iniziando con UppercaseStrategy
// TODO: Elabora il testo 'hello world' e stampa il risultato
// TODO: Passa a LowercaseStrategy
// TODO: Elabora 'HELLO WORLD' e stampa il risultato
// TODO: Passa a TitleCaseStrategy
// TODO: Elabora 'the quick brown fox' e stampa il risultato
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online