Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les tutoriels > Non-Officiels > Programmation > C++ > Lecture du tutoriel

La classe Singleton

Avatar
Auteur : Davidbrcz
Créé : le 05/02/2007 21:52:01
Modifié : le 04/11/2007 14:53:29
Noter et commenter ce tutoriel
Imprimer ce tutoriel
Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Lors du développement d'un projet, on est souvent amené à créer des classes gérant d'autres classes.
Mais si le projet est étalé sur plusieurs codeurs, et que le code n'a pas été mis à jour, imaginez les conséquences d'une double création de classe, gérant par exemple les textures ou les sons d'un jeu.
Bonjour les dégâts de pointeurs déjà libérés, ou déjà alloués.

Mais pour éviter cela, une parade a été trouvée : il s'agit de la classe Singleton, qui permet de n'instancier qu'un seul objet d'un même type au cours de l'exécution d'un programme.
Sommaire du chapitre :

Un peu de théorie

Avant de foncer tête baissée dans le code, je vais vous expliquer le fonctionnement global de cette classe.

Premièrement, étudions ses caractéristiques :


Pour assurer que durant tout le programme, un seul objet sera présent, il faut, de ce fait, déclarer les
constructeurs et destructeurs comme privés. Mais se pose alors le problème de l'allocation de la mémoire.
Il va être résolu par l'utilisation des membres statiques.

En effet, la classe Singleton possédera un pointeur statique de son propre type qu'il suffira d'allouer dans une méthode statique, en vérifiant si celui-ci n'est pas nul. C'est le même principe pour la destruction d'un objet.

Ce qui nous amène au diagramme UML suivant :


Image utilisateur


Implémentation en C++

Voici donc son implémentation en C++ :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class CSingleton
{
    protected:
    int value;
    static CSingleton *singleton;
 
    //le constructeur privé
    CSingleton() : value(0)
    {
        cout<<"Singleton crée"<<endl;
    }
 
    //le destructeur privé
    ~CSingleton()
    {
        cout<<"Singleton détruit"<<endl;
    }
    
    public: 
    
    //un couple d'accesseur / mutateur    
    int GetValue()
    {
        return  value;
    }
    
    void SetValue(int val)
    {
       value=val;
    }
    
    //le "constructeur" public
    static CSingleton* GetInstance()
    {
        if(singleton==0)
        {
            singleton=new CSingleton;
        }
        return singleton;
    }
    
    //le "destructeur" public
    static void Kill()
    { 
    
        if(singleton!=0)
        {
            delete singleton;
            singleton=0;
        }
    }
    
    
};
 
CSingleton *CSingleton::singleton = 0;


Et un petit programme de test :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
 
using namespace std;
 
int main(void)
{
    CSingleton *obj1,*obj2;
    
    obj1=CSingleton::GetInstance();
    obj2=CSingleton::GetInstance();
    
    obj1->SetValue(5);
 
    cout<<obj1->GetValue()<<endl;
    cout<<obj2->GetValue()<<endl;
 
    cout<<obj1<<endl;
    cout<<obj2<<endl;
 
    CSingleton::Kill();
}



Les fonctions SetValue et GetValue sont là pour l'exemple.
N'allez pas penser qu'elles font partie du pattern.Vous pouvez les supprimer si vous le souhaitez.


Et voici le résultat :

Image utilisateur


Aller plus loin grâce aux templates

C'est bien beau d'avoir une classe Singleton, mais si à chaque fois, il faut copier-coller du code, c'est mauvais signe.
On va donc combiner la puissance de l'héritage et des templates pour utiliser à fond notre Singleton.

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
template<typename T> class CSingleton
{
public:
       
    /*
      Cette fonction retourne l'unique instance de l'objet
    */
    static T* GetInstance(void)
    {
        if(singleton==0)
	    {
		singleton = new T;     
	    }
        return singleton;
    }
 
    /*
      Cette fonction tue l'unique instance de l'objet
    */
    static void Kill()
    {
        if(singleton!=0)
	    {
		delete singleton ;
		singleton=0;
	    }
    }
 
 
    //un couple d'accesseur / mutateur    
    int GetValue()
    {
        return  value;
    }
    
    void SetValue(int val)
    {
	value=val;
    }
 
protected:
    
    int value;
 
    CSingleton() : value(0)
    {
        cout<<"Singleton crée"<<endl;
    }
 
    virtual ~CSingleton()
    {
        cout<<"Singleton détruit"<<endl;
    }
    
    static T *singleton;  
};
 
template <typename T> T* CSingleton<T>::singleton = 0;


Et voilà !!
On obtient une classe Singleton toute belle, toute chaude, prête à être utilisée de la façon suivante :

Code : C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class ClassAMettreEnSingleton : public CSingleton<ClassAMettreEnSingleton>
{
friend ClassAMettreEnSingleton* CSingleton<ClassAMettreEnSingleton>::GetInstance();
friend void* CSingleton<ClassAMettreEnSingleton>::Kill();
 
//tous les constructeurs et le destructeur de votre classe privés.
 
ClassAMettreEnSingleton(){}
~ClassAMettreEnSingleton(){}
 
};


Voilà, ce tutoriel touche à sa fin.
Pour toute remarque ou suggestion, envoyez-moi un MP, ou laissez des commentaires.

Licence : Gnu Free Documentation License V 1.2
Auteur : Davidbrcz
Noter et commenter ce tutoriel
Imprimer ce tutoriel

Changer de design | En savoir plus | Plan du site | Politique d'accessibilité | Règles | Fil RSS | XHTML 1.0 | CSS 2.0
Édité par Simple IT SARL : Nous contacter | Revue de presse | Publicité

Y'a plus rien à lire, faut remonter maintenant !

Hébergement web - Correction de tutoriels - Créer un site
Vous souhaitez apparaître ici ? Contactez-nous.

Nombre de connectés 452 Zéros connectés | Requêtes SQL 8 requêtes | Temps de génération de la page : Total (SQL) 0.0262s (0.0132s)