Padrão Singleton
Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 46 de 65.
O padrão Singleton garante que uma classe tenha exatamente um objeto e oferece a cada script uma maneira de acessá-lo. Use-o para coisas das quais um jogo tem apenas uma: as configurações, o sistema de salvamento, o gerenciador de pontuação.
No GDScript, uma static var mantém o objeto único, e uma static func o cria na primeira vez que alguém o solicita:
# 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 pertence à classe, não a um objeto, então todos os scripts veem a mesma variável. A primeira chamada a encontra vazia e cria o objeto; todas as chamadas posteriores retornam esse mesmo objeto.
# 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 são duas variáveis que contêm um objeto, então a alteração feita por meio de a também aparece em b. Para objetos, == é true somente quando os dois lados são o mesmo objeto.
GDScript não pode tornar _init() privado, então nada impede que um script chame GameSettings.new() e obtenha um segundo objeto. O sublinhado em _instance e o método get_instance() são o acordo: os scripts solicitam o objeto, nunca o criam.
Em um projeto Godot, a maneira usual de obter um objeto compartilhado é por meio de um autoload: um script que você registra nas Configurações do Projeto, que o Godot cria uma vez quando o jogo inicia e disponibiliza pelo nome em todos os scripts. Ele é um Singleton gerenciado pelo Godot para você. Os autoloads são configurados no editor, então os desafios aqui criam o padrão em código com static var.
Desafio
FácilCada moeda em um jogo aumenta uma pontuação compartilhada. Faça de ScoreManager um Singleton:
- Uma
static vararmazena o único objeto. static func get_instance()retorna esse objeto, criando-o na primeira chamada. Logo após criá-lo, ele imprimeScore manager created.add_points(points)adiciona pontos ascore.
Em coin.gd, collect() adiciona o value da moeda à pontuação por meio de ScoreManager.get_instance().
O código fornecido lê quantos eventos vêm a seguir e, então, um evento por linha: coin VALUE coleta uma nova moeda, bonus POINTS adiciona pontos diretamente. Após cada evento, ele imprime a pontuação e, ao final, informa se duas chamadas de get_instance() retornam o mesmo objeto. Para coin 5 e bonus 20, a saída é:
Score manager created
Score: 5
Score: 25
Same object: trueSeu código deve ficar em score_manager.gd e coin.gd. main.gd contém o código de entrada/saída fornecido e não pode ser editado.
Experimente você mesmo
extends Node
func _ready():
# Código de entrada/saída fornecido: mantenha-o como está
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()))
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Fundamentos da POO
Arquivos externosIntrodução à POOClasses vs. objetosA palavra-chave selfMétodosPropriedadesConstrutor (_init)Revisão - Calculadora simples4Polimorfismo
Revisitando a Sobrescrita de MétodosDuck TypingClasses e Métodos AbstratosDesign de InterfacesRevisão - Calculadora de Formas7Sinais
O que é um sinal?Declarando e emitindoConectando-se a sinaisSinais com argumentosRevisão - Sistema de saúde10Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite2Propriedades de Classe
Variáveis de Instância vs. EstáticasFunções EstáticasMétodos Setters de PropriedadeMétodos Getters de PropriedadePrivado por ConvençãoRecapitulando: Gerenciador de Conta Bancária5Encapsulamento
Membros públicos e privadosValidação com settersOcultação de informaçõesPropriedades somente para leituraRevisão - Sistema de registros de alunos8Conceitos Avançados de POO
Composição vs. HerançaClasses InternasNós como ComponentesRefCounted vs. NodeEnums em Classes3Herança
Herança básicaA palavra-chave superSobrescrita de métodosCadeias de herançaVerificações de tipo com isRevisão - Hierarquia de funcionários6Métodos especiais
Introdução aos métodos virtuaisO método _to_stringIteradores personalizadosRevisão - Lista personalizada9Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão StrategyPratique por conta própria: Compilador de GDScript online