Aller au contenu

Singleton

Problème

Nous avons une classe qui ne doit être instanciée qu'une seule fois.

Solution

UML Singleton

Source : fr.wikibooks.org - Patrons de conception/Singleton

Exemple d'implémentation

Nous pouvons par exemple définir une classe pour disposer d'un compteur global à l'application comme suit :

class Sequence {

    private static _instance: Sequence = new Sequence();

    private _current = 0;

    private constructor(){
    }

    static getInstance(): Sequence {
        return Sequence._instance ;
    }

    current(): number {
        return this._current;
    }

    next(){
        return this._current++;
    }
}

A l'utilisation, nous aurons :

const sequence = Sequence.getInstance();
console.log(sequence.next()); // 0
console.log(sequence.next()); // 1

Mise en garde

  • Il existe plusieurs variantes d'implémentation (thread safe, lazy loading,...) fonction du langage
  • L'utilisation d'un singleton rend le code difficilement testable
  • L'utilisation d'un singleton rend le code moins flexible (ex : Camera.getInstance() dans un jeu 3D imposerait la présence d'une seule caméra)
  • La singletonite est un anti-pattern :
    • La tentation est grande de l'utiliser pour disposer d'un accès statique à une instance
    • Le problème est le même qu'en cas d'utilisation d'une variable globale
  • Il convient de réserver l'utilisation du singleton dans le cas où l'instance doit être unique.

Variantes

En JavaScript et TypeScript, nous remarquerons que les concepteurs utilisent plutôt des variables globales (ex : navigator.geolocation pour l'API de géolocalisation). Il sera aussi plus naturel d'assurer l'unicité de la construction au niveau d'un module plutôt que de recourir à un constructeur privé :

// helpers/globalSequence.ts - instance globale unique de Sequence
const globalSequence : Sequence = new Sequence();
export default globalSequence ;

Liens utiles