Pattern State
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 98 di 110.
Il pattern State consente a un oggetto di cambiare comportamento quando cambia il suo stato interno, facendo sembrare che l'oggetto abbia cambiato classe. Invece di usare condizioni complesse per gestire stati diversi, incapsuli ogni stato nella propria classe e deleghi il comportamento all'oggetto che rappresenta lo stato corrente.
Il pattern è composto da un Context che mantiene un riferimento allo stato corrente e da classi State che definiscono il comportamento per ogni stato possibile. Quando lo stato del context cambia, anche il suo comportamento cambia automaticamente:
abstract class DocumentState {
void publish(Document doc);
String getStatus();
}
class DraftState implements DocumentState {
@override
void publish(Document doc) {
print('Moving to review...');
doc.setState(ReviewState());
}
@override
String getStatus() => 'Draft';
}
class ReviewState implements DocumentState {
@override
void publish(Document doc) {
print('Document published!');
doc.setState(PublishedState());
}
@override
String getStatus() => 'Under Review';
}
class PublishedState implements DocumentState {
@override
void publish(Document doc) {
print('Already published.');
}
@override
String getStatus() => 'Published';
}
class Document {
DocumentState _state = DraftState();
void setState(DocumentState state) => _state = state;
void publish() => _state.publish(this);
String getStatus() => _state.getStatus();
}
void main() {
var doc = Document();
print(doc.getStatus()); // Draft
doc.publish(); // Moving to review...
print(doc.getStatus()); // Under Review
doc.publish(); // Document published!
print(doc.getStatus()); // Published
}Ogni classe di stato gestisce l'azione publish() in modo diverso e può portare il documento allo stato successivo. La classe Document non ha bisogno di istruzioni condizionali per controllare il suo stato attuale: delega semplicemente all'oggetto stato attivo in quel momento. Questo pattern è ideale per gli oggetti con modalità comportamentali distinte, come l'elaborazione degli ordini, i lettori multimediali o i sistemi di flusso di lavoro.
Sfida
FacileCostruiamo un sistema di semaforo usando il pattern State! Creerai un semaforo che passa attraverso stati diversi, in cui ogni stato determina il colore della luce e il modo in cui passa allo stato successivo.
Organizzerai il codice in due file:
traffic_light.dart: questo file contiene le classi degli stati e il contesto del semaforo. Crea una classe astrattaTrafficLightStatecon due metodi:String getColor(), che restituisce il colore attuale della luce, evoid next(TrafficLight light), che fa passare la luce allo stato successivo. Implementa tre classi di stato concrete:RedState- restituisceREDcome colore e stampaStop! Light is red.quando viene chiamatonext(), quindi passa aGreenStateGreenState- restituisceGREENcome colore e stampaGo! Light is green.quando viene chiamatonext(), quindi passa aYellowStateYellowState- restituisceYELLOWcome colore e stampaCaution! Light is yellow.quando viene chiamatonext(), quindi passa aRedState
TrafficLight(il contesto) che inizia nello statoRedState. Dovrebbe avere un metodosetState()per cambiare lo stato attuale, un metodogetColor()che delega allo stato attuale e un metodochange()che chiamanext()sullo stato attuale.main.dart: importa il file del semaforo e mostra il pattern State in azione. Crea unTrafficLighte stampa il suo colore iniziale. Poi chiamachange()tre volte, stampando il colore dopo ogni cambiamento. In questo modo vedrai il semaforo attraversare tutti gli stati e tornare all'inizio.
Nota che la classe TrafficLight non ha bisogno di condizioni per determinare il comportamento: ogni stato conosce il proprio colore e quale stato viene dopo. Il semaforo si limita a delegare allo stato attivo in quel momento!
Output previsto:
RED
Stop! Light is red.
GREEN
Go! Light is green.
YELLOW
Caution! Light is yellow.
REDProvalo tu
import 'traffic_light.dart';
void main() {
// TODO: Crea un'istanza di TrafficLight
// TODO: Stampa il colore iniziale
// TODO: Chiama change() e stampa il colore (3 volte per attraversare tutti gli stati)
// Primo cambio: RED -> GREEN
// Secondo cambio: GREEN -> YELLOW
// Terzo cambio: YELLOW -> RED
}
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