Patron Singleton
Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 46 sur 65.
Le modèle Singleton garantit qu’une classe possède exactement un objet et offre à chaque script un moyen d’y accéder. Utilise-le pour les éléments dont un jeu ne possède qu’un seul exemplaire : les paramètres, le système de sauvegarde, le gestionnaire de score.
En GDScript, un static var conserve l’unique objet, et une static func le crée la première fois que quelqu’un le demande :
# game_settings.gd
class_name GameSettings
extends RefCounted
static var _instance: GameSettings = null
var volume := 50
static func get_instance() -> GameSettings:
if _instance == null:
_instance = GameSettings.new()
print("Creating settings")
return _instance_instance appartient à la classe, et non à un objet, donc tous les scripts voient la même variable. Le premier appel la trouve vide et crée l’objet ; chaque appel suivant renvoie ce même objet.
# main.gd
var a := GameSettings.get_instance()
var b := GameSettings.get_instance()
a.volume = 80
print(b.volume)
print(a == b)Creating settings
80
truea et b sont deux variables qui contiennent un même objet ; la modification effectuée via a est donc visible via b. Pour les objets, == vaut true uniquement lorsque les deux côtés désignent le même objet.
GDScript ne peut pas rendre _init() privé, donc rien n’empêche un script d’appeler GameSettings.new() et d’obtenir un deuxième objet. Le trait de soulignement dans _instance et la méthode get_instance() constituent la convention : les scripts demandent l’objet, ils ne le créent jamais.
Dans un projet Godot, la méthode habituelle pour obtenir un objet partagé consiste à utiliser un autoload : un script que tu enregistres dans les paramètres du projet, que Godot crée une seule fois au démarrage du jeu et qu’il rend accessible par son nom dans chaque script. C’est un Singleton que Godot gère pour toi. Les autoloads se configurent dans l’éditeur ; les défis présentés ici mettent donc en place le modèle en code avec static var.
Défi
FacileChaque pièce d'un jeu contribue à un score commun. Faites de ScoreManager un Singleton :
- Un
static varcontient l'unique objet. static func get_instance()le renvoie, en le créant lors du premier appel. Juste après l'avoir créé, il afficheScore manager created.add_points(points)ajoute des points àscore.
Dans coin.gd, collect() ajoute la value de la pièce au score via ScoreManager.get_instance().
Le code fourni lit le nombre d'événements à venir, puis un événement par ligne : coin VALUE collecte une nouvelle pièce, bonus POINTS ajoute directement des points. Après chaque événement, il affiche le score et, à la fin, indique si deux appels de get_instance() renvoient le même objet. Pour coin 5 et bonus 20, la sortie est :
Score manager created
Score: 5
Score: 25
Same object: trueVotre code va dans score_manager.gd et coin.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 : conservez-le tel quel
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "coin":
Coin.new(int(parts[1])).collect()
elif parts[0] == "bonus":
ScoreManager.get_instance().add_points(int(parts[1]))
print("Score: %d" % ScoreManager.get_instance().score)
print("Same object: %s" % (ScoreManager.get_instance() == ScoreManager.get_instance()))
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