Menu
CoddyTech

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
true

a 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.

challenge icon

Sfida

Facile

Ogni moneta in un gioco contribuisce a un unico punteggio condiviso. Trasforma ScoreManager in un Singleton:

  • Una static var contiene l'unico oggetto.
  • static func get_instance() lo restituisce, creandolo alla prima chiamata. Subito dopo averlo creato, stampa Score manager created.
  • add_points(points) aggiunge punti a score.

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: true

Il 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()))
quiz iconMettiti alla prova

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

Esercitati da solo: Compilatore GDScript online