Menu
Coddy logo textTech

Modèle Singleton

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 91 sur 104.

Le pattern Singleton garantit qu’une classe ne possède qu’une seule instance dans l’ensemble du programme et fournit un point d’accès global à celle-ci. Cela est utile pour les ressources qui doivent être partagées, comme un gestionnaire de configuration, un enregistreur ou un pool de connexions à une base de données.

L’idée essentielle est de rendre le constructeur privé afin que personne ne puisse créer directement des instances, puis de fournir une méthode statique qui renvoie l’unique instance :

#include <iostream>
#include <string>

class Logger {
private:
    std::string logFile;
    
    // Constructeur privé - empêche l'instanciation directe
    Logger() : logFile("app.log") {}
    
    // Supprime le constructeur de copie et l'opérateur d'affectation
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

public:
    // Méthode statique pour accéder à l'unique instance
    static Logger& getInstance() {
        static Logger instance;  // Créée une seule fois, vit jusqu'à la fin du programme
        return instance;
    }
    
    void log(const std::string& message) {
        std::cout << "[LOG] " << message << "\n";
    }
};

int main() {
    Logger::getInstance().log("Application started");
    
    Logger& logger = Logger::getInstance();
    logger.log("Processing data");
}

Le static Logger instance à l'intérieur de getInstance() est une fonctionnalité de C++11 appelée « variables statiques magiques » : elle est thread-safe et garantit une initialisation unique. En supprimant le constructeur de copie et l'opérateur d'affectation, nous empêchons quiconque de créer des copies de notre singleton.

Utilisez Singleton avec parcimonie : il introduit un état global qui peut rendre les tests plus difficiles. Il convient mieux aux ressources véritablement partagées pour lesquelles le fait d’avoir plusieurs instances poserait problème.

challenge icon

Défi

Facile

Construisons un singleton GameSettings qui gère la configuration d’une application de jeu. C’est un cas d’utilisation parfait pour le modèle Singleton. Vous voulez exactement un gestionnaire de paramètres auquel toutes les parties de votre jeu peuvent accéder, afin de garantir une configuration cohérente partout.

Vous allez organiser votre code dans trois fichiers :

  • GameSettings.h : définissez votre classe singleton qui gère la configuration du jeu.

    Votre classe GameSettings doit stocker trois paramètres en tant que membres privés : difficulty (chaîne de caractères), volume (entier compris entre 0 et 100) et fullscreen (booléen). Initialisez-les avec les valeurs par défaut suivantes : "Normal", 50 et false.

    Implémentez correctement le modèle Singleton :

    • Rendez le constructeur privé
    • Supprimez le constructeur de copie et l’opérateur d’affectation
    • Fournissez une méthode statique getInstance() qui renvoie une référence vers l’unique instance

    Ajoutez les méthodes publiques suivantes pour interagir avec les paramètres :

    • setDifficulty(const std::string& diff) : met à jour la difficulté
    • setVolume(int vol) : met à jour le volume
    • setFullscreen(bool fs) : met à jour le mode plein écran
    • displaySettings() : affiche tous les paramètres actuels
  • GameModule.h : créez un module distinct qui accède au singleton.

    Définissez une fonction appelée applyGamePreset qui prend un nom de préréglage (chaîne de caractères). Cette fonction doit accéder au singleton GameSettings et le configurer en fonction du préréglage :

    • "casual" : définit la difficulté sur "Easy", le volume sur 70 et le plein écran sur false
    • "competitive" : définit la difficulté sur "Hard", le volume sur 30 et le plein écran sur true
    • Tout autre préréglage : conserve les paramètres par défaut inchangés

    Cela montre comment différentes parties d’un programme peuvent accéder à la même instance singleton et la modifier.

  • main.cpp : réunissez tous les éléments pour montrer le singleton en action.

    Lisez deux entrées :

    1. Un nom de préréglage (chaîne de caractères)
    2. Un niveau de volume personnalisé (entier)

    Commencez par afficher les paramètres par défaut initiaux en appelant displaySettings() sur le singleton. Affichez une ligne vide après.

    Appliquez ensuite le préréglage à l’aide de votre fonction applyGamePreset, puis affichez de nouveau les paramètres. Affichez une ligne vide après.

    Enfin, remplacez uniquement le volume par la valeur personnalisée saisie et affichez les paramètres finaux.

La méthode displaySettings() doit afficher le résultat dans ce format exact :

Difficulty: [value]
Volume: [value]
Fullscreen: [yes/no]

Par exemple, avec les entrées casual et 85 :

Difficulty: Normal
Volume: 50
Fullscreen: no

Difficulty: Easy
Volume: 70
Fullscreen: no

Difficulty: Easy
Volume: 85
Fullscreen: no

Avec les entrées competitive et 20 :

Difficulty: Normal
Volume: 50
Fullscreen: no

Difficulty: Hard
Volume: 30
Fullscreen: yes

Difficulty: Hard
Volume: 20
Fullscreen: yes

Remarquez comment main.cpp et GameModule.h accèdent tous deux à la même instance singleton : les modifications effectuées à un endroit sont visibles partout. C’est la puissance du modèle Singleton pour les ressources partagées telles que les paramètres d’un jeu.

Essayez vous-même

#include <iostream>
#include <string>
#include "GameSettings.h"
#include "GameModule.h"

using namespace std;

int main() {
    // Lire les entrées
    string presetName;
    int customVolume;
    cin >> presetName;
    cin >> customVolume;
    
    // TODO: Obtenir l'instance singleton de GameSettings
    
    // TODO: Afficher les paramètres par défaut initiaux
    
    // TODO: Afficher une ligne vide
    
    // TODO: Appliquer le préréglage en utilisant la fonction applyGamePreset
    
    // TODO: Afficher les paramètres après application du préréglage
    
    // TODO: Afficher une ligne vide
    
    // TODO: Remplacer le volume par customVolume
    
    // TODO: Afficher les paramètres finaux
    
    return 0;
}
quiz iconTestez-vous

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

Entraînez-vous par vous-même : Compilateur C++ en ligne