Menu
Coddy logo textTech

Tabla Singleton

Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 63 de 70.

A veces necesitas exactamente una instancia de algo en todo tu programa: un gestor de configuración, un sistema de registro o la configuración del juego. Crear varias copias causaría problemas: ¿cuál tiene los datos correctos? El patrón Singleton garantiza que solo exista una instancia.

En Lua, implementar un Singleton es sorprendentemente sencillo gracias a cómo funcionan los módulos. Cuando usas require para cargar un módulo, Lua almacena en caché el resultado. Las llamadas posteriores a require devuelven la tabla almacenada en caché, no una nueva.

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

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

return GameConfig

Ahora, en cualquier parte de tu programa:

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

config1:setVolume(50)
print(config2.volume)  -- 50 (¡la misma tabla!)

Tanto config1 como config2 hacen referencia exactamente a la misma tabla. Los cambios realizados mediante una variable son visibles a través de la otra. Esto sucede automáticamente porque require almacena el valor devuelto en package.loaded y lo reutiliza.

A diferencia del patrón Factory, que crea objetos nuevos, un Singleton garantiza un estado compartido en toda tu aplicación. Esto es ideal para configuraciones globales a las que varias partes de tu código necesitan acceder y que deben modificar de forma coherente.

challenge icon

Desafío

Fácil

¡Construyamos un gestor de configuración del juego usando el patrón Singleton! Crearás un módulo de configuración que garantiza que cada parte de tu programa acceda exactamente a la misma configuración, sin importar cuántas veces se requiera.

Organizarás tu código en dos archivos:

  • GameSettings.lua: Crea un módulo Singleton que almacene la configuración del juego. Tu tabla de configuración debe incluir musicVolume (con un valor inicial de 70), sfxVolume (con un valor inicial de 100) y difficulty (con un valor inicial de "normal"). Añade tres métodos: :setMusicVolume(value), :setSfxVolume(value) y :setDifficulty(level) para modificar esta configuración. ¡Recuerda devolver la tabla al final del módulo!
  • main.lua: Demuestra que Singleton funciona requiriendo tu módulo GameSettings dos veces en variables diferentes. Usa la primera variable para cambiar el volumen de la música y la dificultad. Después usa la segunda variable para imprimir las tres configuraciones. Si Singleton funciona correctamente, ambas variables hacen referencia a la misma tabla, por lo que los cambios realizados a través de una serán visibles a través de la otra.

Recibirás dos entradas:

  1. Nuevo volumen de la música (un número)
  2. Nuevo nivel de dificultad (una cadena como "easy" o "hard")

Después de modificar la configuración a través de la primera variable, imprime las tres configuraciones usando la segunda variable, cada una en su propia línea y en este orden: volumen de la música, volumen de los efectos de sonido y después dificultad.

Por ejemplo, si las entradas son 50 y hard, la salida debería ser:

50
100
hard

Si las entradas son 25 y easy, la salida debería ser:

25
100
easy

Observa que el volumen de los efectos de sonido permanece en su valor predeterminado de 100, ya que nunca lo cambiamos, pero el volumen de la música y la dificultad reflejan los cambios realizados a través de la primera variable, ¡lo que demuestra que ambas variables apuntan a la misma instancia de Singleton!

Pruébalo tú mismo

-- main.lua - Demuestra el patrón Singleton

-- Leer entradas
local newMusicVolume = tonumber(io.read())
local newDifficulty = io.read()

-- TODO: Requiere el módulo GameSettings en una variable (p. ej., settings1)

-- TODO: Requiere el módulo GameSettings OTRA VEZ en una variable DIFERENTE (p. ej., settings2)
-- (¡Si Singleton funciona correctamente, ambas variables referencian la misma tabla!)

-- TODO: Usa la PRIMERA variable para:
--   - Establece el volumen de la música a newMusicVolume
--   - Establece la dificultad a newDifficulty

-- TODO: Usa la SEGUNDA variable para imprimir la configuración
-- Imprime cada uno en su propia línea: musicVolume, sfxVolume, difficulty
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Lua online