Pattern Singleton
Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 46 di 65.
Il pattern Singleton assicura che una classe abbia esattamente un oggetto e offre a ogni script un unico modo per raggiungerlo. Usalo per gli elementi di cui un gioco ha un solo esemplare: le impostazioni, il sistema di salvataggio, il gestore del punteggio.
In GDScript, una static var contiene l'unico oggetto e una static func lo crea la prima volta che qualcuno lo richiede:
# 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 appartiene alla classe, non a un oggetto, quindi ogni script vede la stessa variabile. La prima chiamata la trova vuota e crea l’oggetto; ogni chiamata successiva restituisce lo stesso oggetto.
# 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 e b sono due variabili che contengono un unico oggetto, quindi la modifica apportata tramite a è visibile anche tramite b. Per gli oggetti, == è true solo quando entrambi i lati fanno riferimento allo stesso oggetto.
GDScript non può rendere privato _init(), quindi niente impedisce a uno script di chiamare GameSettings.new() e ottenere un secondo oggetto. Il trattino basso in _instance e il metodo get_instance() sono l’accordo: gli script chiedono l’oggetto, non lo creano mai.
In un progetto Godot, il modo più comune per ottenere un oggetto condiviso è un autoload: uno script che registri nelle Impostazioni del progetto, che Godot crea una sola volta all'avvio del gioco e rende disponibile per nome in ogni script. È un Singleton che Godot gestisce per te. Gli autoload si configurano nell'editor, quindi le sfide qui costruiscono questo schema nel codice con static var.
Sfida
FacileOgni moneta in un gioco contribuisce a un unico punteggio condiviso. Trasforma ScoreManager in un Singleton:
- Una
static varcontiene l'unico oggetto. static func get_instance()lo restituisce, creandolo alla prima chiamata. Subito dopo averlo creato, stampaScore manager created.add_points(points)aggiunge punti ascore.
In coin.gd, collect() aggiunge il value della moneta al punteggio tramite ScoreManager.get_instance().
Il codice fornito legge quanti eventi seguono, poi un evento per riga: coin VALUE raccoglie una nuova moneta, bonus POINTS aggiunge punti direttamente. Dopo ogni evento stampa il punteggio e, alla fine, indica se due chiamate di get_instance() restituiscono lo stesso oggetto. Per coin 5 e bonus 20, l'output è:
Score manager created
Score: 5
Score: 25
Same object: trueIl tuo codice va in score_manager.gd e coin.gd. main.gd contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
extends Node
func _ready():
# Codice di input/output fornito: lascialo così com'è
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()))
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