Pattern State
Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 54 di 65.
Il pattern State assegna a un oggetto un oggetto di stato separato per ogni modalità in cui può trovarsi. L'oggetto delega il proprio lavoro allo stato corrente, così il suo comportamento cambia quando cambia lo stato.
Per pochi stati, un enum e un match sono sufficienti. Quando ogni stato reagisce a diverse azioni a modo suo, quel match cresce con ogni stato e ogni azione. Il pattern State sposta le regole di ogni stato nella propria classe:
# hero_state.gd
@abstract
class_name HeroState
extends RefCounted
@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroStatehandle() restituisce lo stato successivo: un nuovo oggetto stato a cui passare, oppure self per restare.
# idle_state.gd
class_name IdleState
extends HeroState
func get_state_name() -> String:
return "Idle"
func handle(action: String) -> HeroState:
if action == "run":
return RunState.new()
return selfRunState è scritto allo stesso modo: il suo nome è "Running" e "stop" restituisce IdleState.new(). L'eroe, il contesto, mantiene lo stato corrente e gli chiede cosa fare:
# hero.gd
class_name Hero
extends RefCounted
var state: HeroState = IdleState.new()
func handle_action(action: String) -> void:
var next := state.handle(action)
if next != state:
print(state.get_state_name(), " -> ", next.get_state_name())
state = next# main.gd
var hero := Hero.new()
for action in ["stop", "run", "run", "stop"]:
hero.handle_action(action)Idle -> Running
Running -> IdleLa stessa azione ha significati diversi in stati diversi: "stop" non fa nulla quando l'eroe è inattivo e ferma un eroe in movimento. Ogni regola si trova nella classe del suo stato, quindi un nuovo stato, come il salto, corrisponde a una nuova classe.
Gli stati restituiscono lo stato successivo invece di memorizzare l’eroe. Uno stato che conservasse l’eroe mentre l’eroe conserva lo stato creerebbe un ciclo di riferimenti, e nessuno dei due oggetti verrebbe mai liberato.
Sfida
FacileUna porta è Locked, Closed oppure Open. DoorState (door_state.gd) dichiara get_state_name() e handle(action), e LockedState (locked_state.gd) è già scritto: unlock porta la porta allo stato Closed. Scrivi:
ClosedState.handle():openrestituisce un nuovoOpenState,lockun nuovoLockedState, qualsiasi altra cosaself.OpenState.handle():closerestituisce un nuovoClosedState, qualsiasi altra cosaself.Door.handle_action(action): chiede allo stato corrente quale sarà il prossimo. Se è lo stesso oggetto, stampaACTION: still STATE; altrimenti stampaACTION: OLD -> NEWe passa al nuovo stato.
La porta inizia nello stato Locked. Il codice fornito legge quante azioni seguono, poi un'azione per riga, e stampa lo stato finale. Per open, unlock, open, lock l'output è:
open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: OpenIl tuo codice va in door.gd, closed_state.gd e open_state.gd. main.gd contiene il codice fornito per l'input/output e non può essere modificato.
Provalo tu
extends Node
func _ready():
# Codice di input/output fornito: lascialo così com'è
var door := Door.new()
var count := int(OS.read_string_from_stdin())
for i in count:
door.handle_action(OS.read_string_from_stdin())
print("Final state: ", door.state.get_state_name())
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 esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggetti a confrontoLa parola chiave selfMetodiProprietàCostruttore (_init)Riepilogo - Calcolatrice semplice4Polimorfismo
Ripasso dell'override dei metodiDuck typingClassi e metodi astrattiProgettazione delle interfacceRiepilogo - Calcolatore di forme7Segnali
Che cos'è un segnale?Dichiarare ed emettereCollegarsi ai segnaliSegnali con argomentiRipasso - Sistema della salute10Pattern di progettazione, parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern Composite2Proprietà delle classi
Variabili di istanza e staticheFunzioni staticheSetter delle proprietàGetter delle proprietàPrivato per convenzioneRiepilogo - Gestore di conti bancari5Incapsulamento
Membri pubblici e privatiValidazione con i setterNascondimento delle informazioniProprietà di sola letturaRiepilogo - Sistema di gestione dei dati degli studenti8Concetti avanzati di OOP
Composizione vs ereditarietàClassi interneNodi come componentiRefCounted vs NodeEnum nelle classi11Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiCatene di ereditarietàControlli di tipo con isRipasso - Gerarchia dei dipendenti6Metodi speciali
Introduzione ai metodi virtualiIl metodo _to_stringIteratori personalizzatiRiepilogo - Lista personalizzata9Modelli di progettazione, parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern ObserverPattern StrategyEsercitati da solo: Compilatore GDScript online