Design Pattern : Singleton

Le 12 août 2009 à 14:29

1) Définition du design pattern Singleton

Le singleton est un design pattern (pour les plus francophone un « patron de conception ») qui consiste à restreindre l'instanciation d'une classe à un seul objet (ou à quelques objets).

Dans la pratique, le singleton peut être utilisé dans le cas d’une classe de connexion à une base de données. Le singleton permet de s’assurer qu’une seule instance de la classe connexion est utilisée.

Par contre, attention à ne pas confondre classe statique et Singleton : les deux sont différents et ne s’appliquent pas dans les mêmes cas. Singleton permet d’utiliser un vrai objet, être hérité (classe « normale »)… etc, la classe statique non (ce qui peut être gênant, dans le cas cité plus haut, dans initialisation de la classe).

Ce design pattern est très pratique, à manipuler selon ses besoins, mais attention à l’utilisation de ce pattern en cas de multithreading : il faut éviter que deux threads accèdent en même temps à la création de l’instance de l’objet. Aussi, certains pensent que c’est un antipattern, du fait qu’on le retrouve « dans tout et n’importe quoi ».

Nous allons donc voir son implémentation avec .NET.

image 
2) Exemples d’implémentation C# (thread-safe)

a. Exemple simple

public sealed class MyClass
{
    private static MyClass _instance = null;
    private static readonly object _lock = new object();

    private MyClass()
    {
       
    }

    public static MyClass Instance
    {
        get
        {
            lock(_lock)
            {
                if (_instance==null)
                {
                    _instance = new MyClass();
                }
                return _instance;
            }
        }
    }
}

Il faut souligner le fait qu’on utilise un constructeur privé, en effet, il n’y aurait aucun intérêt de laisser un constructeur publique car on veut justement éviter de créer plusieurs instances (ce qui est tout de même le principe d’un Singleton dans la plupart des cas).

Le bout de code ci-dessus suffirait à la plupart des cas. Mais dans un contexte multithread, il se peut que nous rencontrerions un problème : les deux threads pourraient arriver au même moment dans la section critique. Dans ce cas, l’instance sera crée deux fois et risque de poser problème.

Pour remédier à ce problème, il existe le Double Checked Locking (verrouillage à double test).

b. Double Checked Locking

Comme dit précédemment, le Double Checked Locking va permettre de rendre notre code plus sécurisé dans un contexte multithread. On va vérifier par deux fois si l’instance n’a pas été crée, pour éviter que deux threads le fasse au « même moment » (comme ça peut arriver dans l’exemple a).

public sealed class MyClass
{
    static MyClass _instance = null;
    static readonly object _lock = new object();
                
    private MyClass()
    {     
    }

    public static MyClass Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new MyClass();
                    }
                }
            }
            return _instance;
        }
    }
}

Le Double Checked Locking est considéré comme un antipattern du fait des erreurs difficiles à déceler et du débogage hasardeux que cela implique. Donc ce n’est pas forcément la meilleure solution à utiliser.

Nous allons donc voir à présent une manière beaucoup plus à simple à mettre en place.

c. Static Readonly

Une autre manière d’implémenter un Singleton est de passer par un readonly statique. Cette solution me paraît la meilleure.

public sealed class MyClass
{
    private static readonly MyClass _instance = new MyClass();
    
    private MyClass()
    {
    }
        
    public static MyClass Instance
    {
        get
        {
            return _instance;
        }
    }
 }

3) Conclusion

Le singleton est un pattern assez simple à mettre en place. Malgré tout il faut prendre ses précautions : il faut peser le pour et le contre entre chaque solution pour choisir une implémentation efficace et spécifique à ses besoins.

Plus d’informations sur MSDN.

A bientôt :)

Ajouter un commentaire

biuquote
  • Commentaire
  • Prévisualiser
Loading

A propos de l'auteur

Mathieu Perrein est Software Solutions Architect, MSP de 2010 à 2012.

 

MSP

 

MSP

MSP

 MSPD

MCT

 

Facebook

 

Ce blog est strictement personnel et les opinions exprimées ici n'engagent donc que moi, et pas mon employeur.

Tags

Vous avez désactivé JavaScript ou bien vous possédez une ancienne version d'Adobe Flash Player. Téléchargez la dernière version de Flash Player.