Patron Décorateur
Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 52 sur 65.
Le motif Décorateur ajoute un comportement à un objet en l’enveloppant dans un autre objet possédant les mêmes méthodes. Chaque enveloppe appelle l’objet qu’elle contient et ajoute sa propre contribution, et les enveloppes peuvent être empilées dans n’importe quel ordre.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"Un décorateur étend Weapon, il peut donc être utilisé partout où une arme est attendue, et il contient l’arme qu’il enveloppe :
# fire_enchant.gd
class_name FireEnchant
extends Weapon
var inner: Weapon
func _init(wrapped: Weapon) -> void:
inner = wrapped
func get_damage() -> int:
return inner.get_damage() + 5
func describe() -> String:
return inner.describe() + " + Fire"SharpEnchant s’écrit de la même manière, mais son get_damage() renvoie inner.get_damage() * 2 et son describe() ajoute " + Sharp".
# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())Sword: 10
Sword + Fire + Sharp: 30Les appels se propagent vers l’intérieur : SharpEnchant interroge FireEnchant, qui interroge l’épée. L’épée renvoie 10, le feu le porte à 15, et l’effet tranchant le double pour atteindre 30. Dans l’autre ordre, FireEnchant.new(SharpEnchant.new(Weapon.new())), les dégâts sont de 10 * 2 + 5, soit 25.
Sans décorateurs, chaque combinaison nécessiterait sa propre sous-classe : FireSword, SharpSword, FireSharpSword, et ainsi de suite. Avec eux, deux petites classes couvrent toutes les combinaisons, et un nouvel enchantement ne nécessite qu’un fichier supplémentaire.
Défi
MoyenUn café prépare des boissons à l’aide de décorateurs. Beverage (beverage.gd) déclare cost() et description() ; Espresso (espresso.gd, $3) et Tea (tea.gd, $2) sont écrits. Chaque décorateur stocke la boisson qu’il enveloppe dans inner (les constructeurs sont écrits). Redéfinissez cost() et description() dans :
Milk: coûte1de plus et ajoute+ Milkà la description.Mocha: coûte2de plus et ajoute+ Mocha.Large: double le coût de tout ce qu’il contient et placeLargedevant la description.
Le code fourni lit le nombre de commandes à suivre, puis une commande par ligne : la boisson (espresso ou tea) et ses suppléments, appliqués de gauche à droite. Pour espresso milk large et tea mocha milk, la sortie est :
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5Votre code va dans milk.gd, mocha.gd et large.gd. main.gd contient le code d’entrée/sortie fourni et ne peut pas être modifié.
Essayez vous-même
extends Node
func _ready():
# Code d'entrée/sortie fourni : ne le modifiez pas
var count := int(OS.read_string_from_stdin())
for i in count:
var words := OS.read_string_from_stdin().split(" ")
var drink: Beverage = Tea.new()
if words[0] == "espresso":
drink = Espresso.new()
for extra in words.slice(1):
match extra:
"milk":
drink = Milk.new(drink)
"mocha":
drink = Mocha.new(drink)
"large":
drink = Large.new(drink)
print("%s: $%d" % [drink.description(), drink.cost()])
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