Menu
Coddy logo textTech

Tabela Singleton

Parte da seção Programação Orientada a Objetos do Journey de Lua da Coddy — lição 63 de 70.

Às vezes, você precisa de exatamente uma instância de algo em todo o seu programa — um gerenciador de configuração, um sistema de log ou configurações de jogo. Criar múltiplas cópias causaria problemas: qual delas possui os dados corretos? O padrão Singleton garante que apenas uma instância exista.

Em Lua, implementar um Singleton é surpreendentemente simples graças à forma como os módulos funcionam. Quando você usa require em um módulo, o Lua faz o cache do resultado. Chamadas subsequentes para require retornam a tabela em cache, não uma nova.

-- GameConfig.lua
local GameConfig = {
    volume = 80,
    difficulty = "normal"
}

function GameConfig:setVolume(v)
    self.volume = v
end

return GameConfig

Agora, em qualquer lugar do seu programa:

local config1 = require("GameConfig")
local config2 = require("GameConfig")

config1:setVolume(50)
print(config2.volume)  -- 50 (mesma tabela!)

Tanto config1 quanto config2 referenciam exatamente a mesma tabela. Alterações feitas através de uma variável são visíveis através da outra. Isso acontece automaticamente porque o require do Lua armazena o valor retornado em package.loaded e o reutiliza.

Ao contrário do padrão Factory, que cria novos objetos, um Singleton garante um estado compartilhado em toda a sua aplicação. Isso é ideal para configurações globais que múltiplas partes do seu código precisam acessar e modificar de forma consistente.

challenge icon

Desafio

Fácil

Vamos construir um gerenciador de configurações de jogo usando o padrão Singleton! Você criará um módulo de configuração que garante que cada parte do seu programa acesse exatamente as mesmas configurações — não importa quantas vezes ele seja requisitado.

Você organizará seu código em dois arquivos:

  • GameSettings.lua: Crie um módulo Singleton que armazena a configuração do jogo. Sua tabela de configurações deve incluir musicVolume (começando em 70), sfxVolume (começando em 100) e difficulty (começando em "normal"). Adicione três métodos: :setMusicVolume(value), :setSfxVolume(value) e :setDifficulty(level) para modificar essas configurações. Lembre-se de retornar a tabela ao final do módulo!
  • main.lua: Demonstre que o Singleton funciona requisitando seu módulo GameSettings duas vezes em variáveis diferentes. Use a primeira variável para alterar o volume da música e a dificuldade. Em seguida, use a segunda variável para imprimir todas as três configurações — se o Singleton estiver funcionando corretamente, ambas as variáveis referenciam a mesma tabela, portanto, as alterações feitas por uma são visíveis pela outra.

Você receberá duas entradas:

  1. Novo volume de música (um número)
  2. Novo nível de dificuldade (uma string como "easy" ou "hard")

Após modificar as configurações através da primeira variável, imprima as três configurações usando a segunda variável, cada uma em sua própria linha nesta ordem: volume da música, volume de sfx e, em seguida, dificuldade.

Por exemplo, se as entradas forem 50 e hard, a saída deve ser:

50
100
hard

Se as entradas forem 25 e easy, a saída deve ser:

25
100
easy

Observe que o volume de sfx permanece em seu valor padrão de 100, pois nunca o alteramos — mas o volume da música e a dificuldade refletem as alterações feitas por meio da primeira variável, provando que ambas as variáveis apontam para a mesma instância Singleton!

Experimente você mesmo

-- main.lua - Demonstra o padrão Singleton

-- Lê as entradas
local newMusicVolume = tonumber(io.read())
local newDifficulty = io.read()

-- TODO: Importar o módulo GameSettings para uma variável (ex: settings1)

-- TODO: Importar o módulo GameSettings NOVAMENTE para uma variável DIFERENTE (ex: settings2)
-- (Se o Singleton funcionar corretamente, ambas as variáveis referenciarão a mesma tabela!)

-- TODO: Use a PRIMEIRA variável para:
--   - Definir o volume da música para newMusicVolume
--   - Definir a dificuldade para newDifficulty

-- TODO: Use a SEGUNDA variável para imprimir as configurações
-- Imprima cada um em sua própria linha: musicVolume, sfxVolume, difficulty
quiz iconTeste seus conhecimentos

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