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 los ajustes de un juego. Crear múltiples copias causaría problemas: ¿cuál de ellas tiene los datos correctos? El patrón Singleton asegura 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 un módulo, Lua guarda el resultado en caché. 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 (¡misma tabla!)

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

A diferencia del patrón Factory que crea nuevos objetos, un Singleton garantiza un estado compartido en toda su aplicación. Esto es ideal para configuraciones globales a las que múltiples partes de su código necesitan acceder y modificar de manera consistente.

challenge icon

Desafío

Fácil

¡Vamos a construir un gestor de configuración de 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 los mismos ajustes, sin importar cuántas veces sea requerido.

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 ajustes debe incluir musicVolume (empezando en 70), sfxVolume (empezando en 100) y difficulty (empezando en "normal"). Añade tres métodos: :setMusicVolume(value), :setSfxVolume(value) y :setDifficulty(level) para modificar estos ajustes. ¡Recuerda devolver la tabla al final del módulo!
  • main.lua: Demuestra que el 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. Luego usa la segunda variable para imprimir los tres ajustes; si el Singleton funciona correctamente, ambas variables hacen referencia a la misma tabla, por lo que los cambios realizados a través de una son visibles a través de la otra.

Recibirás dos entradas:

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

Después de modificar los ajustes a través de la primera variable, imprime los tres ajustes usando la segunda variable, cada uno en su propia línea en este orden: volumen de música, volumen de sfx y luego 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 sfx 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 Singleton!

Pruébalo tú mismo

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

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

-- TODO: Requerir el módulo GameSettings en una variable (por ejemplo, settings1)

-- TODO: Requerir el módulo GameSettings OTRA VEZ en una variable DIFERENTE (por ejemplo, settings2)
-- (¡Si Singleton funciona correctamente, ambas variables hacen referencia a la misma tabla!)

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

-- TODO: Usar la SEGUNDA variable para imprimir la configuración
-- Imprimir 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