Patron État
Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 54 sur 65.
Le patron État attribue à un objet un objet d’état distinct pour chaque mode dans lequel il peut se trouver. L’objet délègue son travail à l’état actuel, de sorte que son comportement change lorsque l’état change.
Pour quelques états, une énumération et un match suffisent. Lorsque chaque état réagit à plusieurs actions à sa manière, ce match s’allonge à chaque état et à chaque action. Le patron État déplace les règles de chaque état dans sa propre classe :
# hero_state.gd
@abstract
class_name HeroState
extends RefCounted
@abstract func get_state_name() -> String
@abstract func handle(action: String) -> HeroStatehandle() renvoie l’état suivant : un nouvel objet d’état vers lequel passer, ou self pour rester dans l’état actuel.
# 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 s’écrit de la même manière : son nom est "Running", et "stop" renvoie IdleState.new(). Le héros, le contexte, conserve l’état actuel et lui demande quoi faire :
# 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 même action signifie des choses différentes selon l’état : "stop" ne fait rien à l’arrêt et arrête un héros en mouvement. Chaque règle se trouve dans la classe de son état, donc un nouvel état, comme le saut, correspond à une nouvelle classe.
Les états renvoient l’état suivant au lieu de stocker le héros. Un état qui conserverait le héros tandis que le héros conserverait l’état créerait un cycle de références, et aucun des deux objets ne serait jamais libéré.
Défi
FacileUne porte est Locked, Closed ou Open. DoorState (door_state.gd) déclare get_state_name() et handle(action), et LockedState (locked_state.gd) est écrit : unlock fait passer la porte à l’état Closed. Écris :
ClosedState.handle():openrenvoie un nouvelOpenState,lockun nouvelLockedState, et toute autre valeurself.OpenState.handle():closerenvoie un nouveauClosedState, et toute autre valeurself.Door.handle_action(action): demande à l’état actuel quel est le suivant. S’il s’agit du même objet, afficheACTION: still STATE; sinon, afficheACTION: OLD -> NEWet passe au nouvel état.
La porte commence à l’état Locked. Le code fourni lit le nombre d’actions à effectuer, puis une action par ligne, et affiche l’état final. Pour open, unlock, open, lock, la sortie est :
open: still Locked
unlock: Locked -> Closed
open: Closed -> Open
lock: still Open
Final state: OpenTon code va dans door.gd, closed_state.gd et open_state.gd. main.gd contient le code fourni pour les entrées et sorties et ne peut pas être modifié.
Essayez vous-même
extends Node
func _ready():
# Code d'entrée/sortie fourni : conservez-le tel quel
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())
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé selfMéthodesPropriétésConstructeur (_init)Récapitulatif - Calculatrice simple4Polymorphisme
Retour sur la redéfinition des méthodesTypage canardClasses et méthodes abstraitesConception d’interfacesRécapitulatif – Calculateur de formes7Signaux
Qu’est-ce qu’un signal ?Déclarer et émettreSe connecter aux signauxSignaux avec argumentsRécapitulatif - système de santé10Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron Composite2Propriétés de classe
Variables d’instance et variables statiquesFonctions statiquesSetters de propriétésGetters de propriétésPrivé par conventionRécapitulatif - Gestionnaire de comptes bancaires5Encapsulation
Membres publics et privésValidation avec les méthodes setterMasquage de l’informationPropriétés en lecture seuleRécapitulatif - Système de dossiers étudiants8Concepts avancés de la POO
Composition ou héritageClasses internesLes nœuds comme composantsRefCounted ou NodeEnums dans les classes3Héritage
Héritage de baseLe mot-clé superRedéfinition de méthodesChaînes d’héritageVérifier les types avec isRécapitulatif – Hiérarchie des employés6Méthodes spéciales
Introduction aux méthodes virtuellesLa méthode _to_stringItérateurs personnalisésRécapitulatif – Liste personnalisée9Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron StrategyEntraînez-vous par vous-même : Compilateur GDScript en ligne