Table Singleton
Fait partie de la section Programmation orientée objet du Journey Lua de Coddy. Leçon 63 sur 70.
Parfois, vous avez besoin d’une seule instance exactement d’un élément dans tout votre programme : un gestionnaire de configuration, un système de journalisation ou des paramètres de jeu. Créer plusieurs copies causerait des problèmes : laquelle contient les bonnes données ? Le modèle Singleton garantit qu’une seule instance existe.
En Lua, implémenter un Singleton est étonnamment simple grâce au fonctionnement des modules. Lorsque vous require un module, Lua met le résultat en cache. Les appels ultérieurs à require renvoient la table mise en cache, et non une nouvelle table.
-- GameConfig.lua
local GameConfig = {
volume = 80,
difficulty = "normal"
}
function GameConfig:setVolume(v)
self.volume = v
end
return GameConfig
Maintenant, n’importe où dans ton programme :
local config1 = require("GameConfig")
local config2 = require("GameConfig")
config1:setVolume(50)
print(config2.volume) -- 50 (même table !)
Les deux config1 et config2 font référence exactement à la même table. Les changements effectués par l’intermédiaire d’une variable sont visibles via l’autre. Cela se produit automatiquement, car Lua stocke la valeur retournée dans package.loaded avec require, puis la réutilise.
Contrairement au pattern Factory qui crée de nouveaux objets, un Singleton garantit un état partagé dans toute votre application. C’est idéal pour les paramètres globaux auxquels plusieurs parties de votre code doivent accéder et qu’elles doivent modifier de manière cohérente.
Défi
FacileConstruisons un gestionnaire de paramètres de jeu en utilisant le modèle Singleton ! Vous allez créer un module de configuration qui garantit que chaque partie de votre programme accède exactement aux mêmes paramètres, quel que soit le nombre de fois où le module est requis.
Vous allez organiser votre code sur deux fichiers :
GameSettings.lua: créez un module Singleton qui stocke la configuration du jeu. Votre table de paramètres doit incluremusicVolume(commençant à 70),sfxVolume(commençant à 100) etdifficulty(commençant à"normal"). Ajoutez trois méthodes ::setMusicVolume(value),:setSfxVolume(value)et:setDifficulty(level)pour modifier ces paramètres. N'oubliez pas de retourner la table à la fin du module !main.lua: démontrez que le Singleton fonctionne en requérant votre module GameSettings deux fois dans des variables différentes. Utilisez la première variable pour modifier le volume de la musique et la difficulté. Utilisez ensuite la deuxième variable pour afficher les trois paramètres. Si le Singleton fonctionne correctement, les deux variables font référence à la même table ; les modifications effectuées via l'une sont donc visibles via l'autre.
Vous recevrez deux entrées :
- Nouveau volume de la musique (un nombre)
- Nouveau niveau de difficulté (une chaîne comme
"easy"ou"hard")
Après avoir modifié les paramètres via la première variable, affichez les trois paramètres à l'aide de la deuxième variable, chacun sur sa propre ligne et dans cet ordre : volume de la musique, volume des effets sonores, puis difficulté.
Par exemple, si les entrées sont 50 et hard, la sortie doit être :
50
100
hardSi les entrées sont 25 et easy, la sortie doit être :
25
100
easyRemarquez que le volume des effets sonores reste à sa valeur par défaut de 100 puisque nous ne l'avons jamais modifié, tandis que le volume de la musique et la difficulté reflètent les modifications effectuées via la première variable, ce qui prouve que les deux variables pointent vers la même instance Singleton !
Essayez vous-même
-- main.lua - Démontrer le pattern Singleton
-- Lire les entrées
local newMusicVolume = tonumber(io.read())
local newDifficulty = io.read()
-- TODO: Require le module GameSettings dans une variable (p. ex., settings1)
-- TODO: Require le module GameSettings ENCORE dans une variable DIFFÉRENTE (p. ex., settings2)
-- (Si le Singleton fonctionne correctement, les deux variables référencent la même table !)
-- TODO: Utiliser la PREMIÈRE variable pour :
-- - Définir le volume de la musique à newMusicVolume
-- - Définir la difficulté à newDifficulty
-- TODO: Utiliser la DEUXIÈME variable pour afficher les paramètres
-- Afficher chacun sur sa propre ligne : musicVolume, sfxVolume, difficulty
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation orientée objet
1Le concept de « self »
Tables avec fonctions« self » expliciteLa syntaxe avec deux-pointsPoint vs deux-pointsRécapitulatif - Point mobile4Projet : Banque numérique
Configuration du projetMéthode de dépôt7Polymorphisme et Redéfinition
Redéfinition de méthodesAppeler des méthodes parentesDuck TypingInterface communeVérification du typeRécapitulatif - Rôles des employés10Projet : Gestionnaire de formes
Configuration du projetClasse RectangleClasse CercleMéthode PérimètreCollection de formesAire totaleFiltrer les formes2Modèle de prototype de classe
Le concept de prototypeLiaison avec __indexLe constructeur :new()Initialisation des attributsInstances indépendantesRécapitulatif - Usine de voitures5Surcharge d'opérateurs en POO
Additionner des objetsSoustraire des objetsConcaténer des objetsComparer des objets (<, >)Récapitulatif - Calculs de portefeuille8Encapsulation
Conventions de nommageClosures pour la confidentialitéAccès via les ClosuresTables en lecture seuleLogique de validationRécapitulatif - Coffre-fort sécurisé11Patrons de conception (Lite)
Fonctions FactoryTable SingletonPatron IteratorObserver (Écouteur)Récapitulatif - Logger Factory3État et comportement des objets
Variables d'instanceMéthodes GetterMéthodes SetterPropriétés calculéesFormatage de chaînesVérifications d'égalitéRécapitulatif - Note de l'étudiant6Bases de l'héritage
Mise en place de l'héritageHériter des méthodesÉtendre le constructeurAjouter des méthodes enfantsPartagé vs UniqueRécapitulatif - Hiérarchie des formesEntraînez-vous par vous-même : Compilateur Lua en ligne