Patron Commande
Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 50 sur 65.
Le modèle Command transforme une action en objet. L’objet stocke tout ce dont vous avez besoin pour exécuter l’action, afin que vous puissiez le conserver dans une liste, l’exécuter plus tard ou l’annuler.
Chaque commande possède les deux mêmes méthodes, déclarées par une classe parente abstraite :
# command.gd
@abstract
class_name Command
extends RefCounted
@abstract func execute() -> void
@abstract func undo() -> voidUne commande concrète conserve l’objet sur lequel elle agit, appelé le récepteur, ainsi que les données de l’action. Ici, le récepteur est un Hero avec un var x := 0 :
# move_command.gd
class_name MoveCommand
extends Command
var hero: Hero
var dx: int
func _init(target: Hero, step: int) -> void:
hero = target
dx = step
func execute() -> void:
hero.x += dx
func undo() -> void:
hero.x -= dxL’invocateur exécute les commandes et s’en souvient. Il n’a jamais besoin de savoir ce que fait une commande :
# command_history.gd
class_name CommandHistory
extends RefCounted
var done: Array[Command] = []
func run(command: Command) -> void:
command.execute()
done.append(command)
func undo_last() -> void:
if done.is_empty():
return
var last: Command = done.pop_back()
last.undo()# main.gd
var hero := Hero.new()
var history := CommandHistory.new()
history.run(MoveCommand.new(hero, 3))
history.run(MoveCommand.new(hero, 2))
print(hero.x)
history.undo_last()
print(hero.x)5
3L’historique est une pile : pop_back() récupère la commande la plus récente, donc l’annulation remonte les actions dans l’ordre inverse. Les mêmes objets permettent de réassocier les touches (une touche correspond à une commande), de rejouer les actions (exécuter à nouveau la liste enregistrée) et de gérer des files de tours.
Les références vont dans un seul sens : les commandes pointent vers le héros, et le héros ne sait rien à leur sujet. Si le héros stockait également ses commandes, les objets se maintiendraient mutuellement en vie et ne seraient jamais libérés.
Défi
FacileUn héros se déplace sur une grille, et chaque déplacement peut être annulé. Command (command.gd) déclare execute() et undo(), et Hero (hero.gd) possède x, y et position_text(). Écrivez :
MoveCommand: le constructeur stocke le héros et les passtep_xetstep_y.execute()ajoute les pas àxetydu héros, etundo()les soustrait.CommandHistory:run(command)exécute la commande et la stocke.undo_last()annule la commande stockée la plus récente, la supprime et renvoietrue; si rien n’est stocké, elle renvoiefalse.
Le code fourni lit le nombre d’actions à effectuer, puis lit une action par ligne (up, down, left, right ou undo) et affiche la position après chacune d’elles. up diminue y de un. Pour right, up, undo, undo, undo, la sortie est :
right -> (1, 0)
up -> (1, -1)
undo -> (1, 0)
undo -> (0, 0)
Nothing to undoVotre code doit être placé dans move_command.gd et command_history.gd. main.gd contient le code fourni d’entrée/sortie 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 hero := Hero.new()
var history := CommandHistory.new()
var steps := {"up": [0, -1], "down": [0, 1], "left": [-1, 0], "right": [1, 0]}
var count := int(OS.read_string_from_stdin())
for i in count:
var action := OS.read_string_from_stdin()
if action == "undo":
if history.undo_last():
print("undo -> ", hero.position_text())
else:
print("Nothing to undo")
else:
var step: Array = steps[action]
history.run(MoveCommand.new(hero, step[0], step[1]))
print(action, " -> ", hero.position_text())
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