Pattern Command
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 94 di 110.
Il pattern Command incapsula una richiesta come oggetto, consentendoti di parametrizzare i client con richieste diverse, mettere in coda le operazioni o supportare la funzionalità di annullamento. Invece di chiamare direttamente un metodo, racchiudi l’azione in un oggetto comando che può essere memorizzato, passato ad altri o eseguito in seguito.
Il pattern prevede tre componenti chiave: un’interfaccia Command con un metodo execute, Comandi concreti che implementano azioni specifiche e un Ricevitore che esegue il lavoro vero e proprio. Un Invocatore facoltativo attiva i comandi senza sapere cosa fanno:
abstract class Command {
void execute();
}
class Light {
void turnOn() => print('Light is ON');
void turnOff() => print('Light is OFF');
}
class TurnOnCommand implements Command {
final Light light;
TurnOnCommand(this.light);
@override
void execute() => light.turnOn();
}
class TurnOffCommand implements Command {
final Light light;
TurnOffCommand(this.light);
@override
void execute() => light.turnOff();
}
class RemoteControl {
Command? _command;
void setCommand(Command command) {
_command = command;
}
void pressButton() {
_command?.execute();
}
}
void main() {
var light = Light();
var remote = RemoteControl();
remote.setCommand(TurnOnCommand(light));
remote.pressButton(); // Light is ON
remote.setCommand(TurnOffCommand(light));
remote.pressButton(); // Light is OFF
}RemoteControl non sa nulla delle luci: esegue semplicemente il comando che gli viene assegnato. Questo disaccoppiamento rende facile aggiungere nuovi comandi senza modificare l'invoker. Il pattern Command è ideale per implementare sistemi di annullamento/ripristino, code di attività o registrazione di macro, quando è necessario trattare le azioni come oggetti di prima classe.
Sfida
FacileCostruiamo un sistema di comandi per un editor di testo usando il pattern Command! Creerai un sistema che incapsula le operazioni sul testo come oggetti comando, consentendo a un editor di eseguire diverse azioni senza conoscere i dettagli di ciascuna operazione. Questo è un classico caso d’uso del pattern Command: immaginalo come un sistema di annullamento/ripristino in cui ogni azione viene memorizzata come oggetto.
Organizzerai il codice in due file:
commands.dart: crea qui il tuo sistema di comandi. Inizia con una classe astrattaCommandche dichiara un metodoexecute(). Poi crea una classeTextDocument(il ricevitore) che contiene un campoString content(inizialmente vuoto) e dispone di tre metodi:append(String text)- aggiunge testo alla fine del contenutoclear()- imposta il contenuto su una stringa vuotashow()- stampaDocument: [content]
TextDocument:AppendCommand- riceve un documento e del testo nel costruttore e aggiunge il testo quando viene eseguitoClearCommand- riceve un documento nel costruttore e lo svuota quando viene eseguitoShowCommand- riceve un documento nel costruttore e ne mostra il contenuto quando viene eseguito
TextEditor(l’invocatore) che memorizza un elenco di comandi. Dovrebbe avere un metodoaddCommand(Command command)per accodare i comandi e un metodorunAll()che esegue tutti i comandi accodati nell’ordine.main.dart: importa il tuo file dei comandi e mostra il pattern Command. Crea unTextDocumente unTextEditor. Accoda i seguenti comandi nell’ordine: aggiungiHello, aggiungiWorld, mostra il documento, aggiungi!, mostra di nuovo, svuota il documento e mostralo un’ultima volta. Poi esegui tutti i comandi accodati.
Nota come TextEditor non sappia nulla dell’aggiunta, dello svuotamento o della visualizzazione: si limita a eseguire i comandi che gli vengono assegnati. Questo disaccoppiamento è l’essenza del pattern Command!
Output previsto:
Document: Hello World
Document: Hello World!
Document: Provalo tu
import 'commands.dart';
void main() {
// TODO: Crea un'istanza di TextDocument
// TODO: Crea un'istanza di TextEditor
// TODO: Metti in coda i seguenti comandi nell'ordine indicato:
// 1. Aggiungi "Hello"
// 2. Aggiungi " World"
// 3. Mostra il documento
// 4. Aggiungi "!"
// 5. Mostra di nuovo il documento
// 6. Cancella il contenuto del documento
// 7. Mostra il documento un'ultima volta
// TODO: Esegui tutti i comandi in coda
}
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