Menu
Coddy logo textTech

Tabela Singleton

Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 63 z 70.

Czasami w całym programie potrzebujesz dokładnie jednej instancji czegoś: menedżera konfiguracji, systemu logowania lub ustawień gry. Tworzenie wielu kopii mogłoby powodować problemy: która z nich ma prawidłowe dane? Wzorzec Singleton gwarantuje, że istnieje tylko jedna instancja.

W Lua implementacja wzorca Singleton jest zaskakująco prosta dzięki temu, jak działają moduły. Gdy używasz require do załadowania modułu, Lua buforuje wynik. Kolejne wywołania require zwracają zbuforowaną tabelę, a nie nową.

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

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

return GameConfig

Teraz, w dowolnym miejscu programu:

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

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

Zarówno config1, jak i config2 odwołują się do dokładnie tej samej tablicy. Zmiany wprowadzone za pomocą jednej zmiennej są widoczne przez drugą. Dzieje się tak automatycznie, ponieważ Lua zapisuje zwróconą wartość w package.loaded i używa jej ponownie podczas wywołania require.

W przeciwieństwie do wzorca Fabryki, który tworzy nowe obiekty, Singleton gwarantuje współdzielony stan w całej aplikacji. To idealne rozwiązanie w przypadku ustawień globalnych, do których różne części kodu muszą mieć dostęp i które muszą modyfikować w spójny sposób.

challenge icon

Wyzwanie

Łatwy

Stwórzmy menedżer ustawień gry z wykorzystaniem wzorca Singleton! Utworzysz moduł konfiguracji, który zapewni, że każda część programu będzie korzystać z dokładnie tych samych ustawień — bez względu na to, ile razy moduł zostanie załadowany.

Rozmieścisz kod w dwóch plikach:

  • GameSettings.lua: Utwórz moduł Singleton przechowujący konfigurację gry. Tabela ustawień powinna zawierać musicVolume (wartość początkowa 70), sfxVolume (wartość początkowa 100) oraz difficulty (wartość początkowa "normal"). Dodaj trzy metody: :setMusicVolume(value), :setSfxVolume(value) i :setDifficulty(level), które będą modyfikować te ustawienia. Pamiętaj, aby na końcu modułu zwrócić tabelę!
  • main.lua: Pokaż, że Singleton działa, ładując moduł GameSettings dwukrotnie do różnych zmiennych. Użyj pierwszej zmiennej, aby zmienić głośność muzyki i poziom trudności. Następnie użyj drugiej zmiennej, aby wypisać wszystkie trzy ustawienia. Jeśli Singleton działa poprawnie, obie zmienne odwołują się do tej samej tabeli, więc zmiany wprowadzone za pomocą jednej będą widoczne za pomocą drugiej.

Otrzymasz dwa dane wejściowe:

  1. Nowa głośność muzyki (liczba)
  2. Nowy poziom trudności (ciąg znaków, taki jak "easy" lub "hard")

Po zmodyfikowaniu ustawień za pomocą pierwszej zmiennej wypisz trzy ustawienia, korzystając z drugiej zmiennej, każde w osobnym wierszu i w następującej kolejności: głośność muzyki, głośność efektów dźwiękowych, a następnie poziom trudności.

Na przykład, jeśli dane wejściowe to 50 i hard, wynikiem powinno być:

50
100
hard

Jeśli dane wejściowe to 25 i easy, wynikiem powinno być:

25
100
easy

Zwróć uwagę, że głośność efektów dźwiękowych pozostaje domyślną wartością 100, ponieważ jej nie zmienialiśmy, ale głośność muzyki i poziom trudności odzwierciedlają zmiany wprowadzone za pomocą pierwszej zmiennej, co dowodzi, że obie zmienne wskazują tę samą instancję Singletona!

Spróbuj swoich sił

-- main.lua - Demonstronstracja wzorca Singleton

-- Wczytaj dane wejściowe
local newMusicVolume = tonumber(io.read())
local newDifficulty = io.read()

-- TODO: Załaduj moduł GameSettings do zmiennej (np. settings1)

-- TODO: Załaduj moduł GameSettings PONOWNIE do INNEJ zmiennej (np. settings2)
-- (Jeśli Singleton działa poprawnie, obie zmienne odwołują się do tej samej tabeli!)

-- TODO: Użyj PIERWSZEJ zmiennej, aby:
--   - Ustawić głośność muzyki na newMusicVolume
--   - Ustawić poziom trudności na newDifficulty

-- TODO: Użyj DRUGIEJ zmiennej, aby wypisać ustawienia
-- Wypisz każdą wartość w osobnej linii: musicVolume, sfxVolume, difficulty
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Lua online