Le Singleton

Ce Pattern va nous permettre d’avoir un modèle d’instanciation d’une classe qui va nous assurer qu’une et une seule et unique instance de cette classe nous sera fourni.

Intention

Disposition d’esprit par laquelle on se propose délibérément un but.

Ce Pattern va nous permettre d’avoir un modèle d’instanciation d’une classe qui va nous assurer qu’une et une seule et unique instance de cette classe nous sera fourni.

De plus, ce Pattern va nous mettre à disposition une méthode servant de point d’accès global à l’instance.

Problème(s)

Question à résoudre par un raisonnement scientifique et constituant un exercice.

Ce Pattern va nous permettre de résoudre deux problèmes, même si à cause de cet état de faite, il viole le principe de Responsabilité Unique (c’est le S du principe SOLID).

Instance Unique

Instanciation d’une et une seule classe

Il existe des circonstances où on ne souhaite qu’une seule instance d’une classe quelque soit le moment du cycle de vie de l’application. Imaginez-vous que vous avez créé une instance d’une classe, vous recevez donc son instanciation. Vous vous dites à un moment donné pendant le cycle de vie de votre application que vous avez besoin d’une nouvelle instance. Mais au lieu de cela, avec le Singleton vous recevrez l’instance qui a été instanciée auparavant.

L’important d’avoir à l’esprit c’est que nativement le constructeur nous retourne tout le temps une nouvelle instance de l’objet. Donc celui-ci, dans le singleton, sa conception sera changé pour répondre à notre besoin d’instance unique.

Exemple

Lorsque l’on veut contrôler l’accès à des ressources partagées ;
Lorsque l’on utilise la Pattern de l’Abstract Factory dont il n’est pas nécessaire de créer plusieurs instance.

Accès Global

Récupération ou instanciation toujours par le même point d’accès.

Le but est de fournir a tout client voulant une “instance” de la classe d’avoir le même point d’accès que tout les autres. Ces clients peuvent même ne pas se rendre compte qu’ils utilisent la même instance commune. Ce qu’il faut avoir à l’esprit c’est que ce Pattern va protéger l’instance unique de la classe contre tout éventuels écrasement de celui-ci par un autre processus/code. Ce qui vaut à dire qu’il n’existera pas de variable globale à mettre en place.

L’accès global veut dire, plus que n’importe quels clients de n’importe où dans l’application pourra avoir accès à cette fonction pour récupérer l’instance de le classe.

Une “Guidance” dans le faite de pouvoir mettre à disposition de toute l’application ce Singleton est de l’avoir dans un classe qui est indépendant du reste du code, mais uniquement si le code intégrale en a besoin.

Solution

“Un problème sans solution est un problème mal posé.”
[Albert Einstein]

De manière général, l’implémentation du Design Pattern Singleton, comprend à minima deux étapes fondamentales

Le constructeur

Il faut rendre le constructeur par défaut privé car il faut pouvoir empêcher quiconque de pouvoir instancier la classe sans que l’on es la main mise sur cette instanciation. Il faut impérativement passer par la méthode globale pour récupérer l’instance unique de notre objet.

Méthode d’accès globale

Mettre en place une méthode de création statique qui va agir comme le constructeur. Encapsuler dans cette méthode la mécanique sera schématiquement la suivante.
La méthode regarde si l’instance de l’objet a déjà été créée si oui elle la retourne à l’appelant sinon avant cela elle effectue un appel au constructeur par défaut de la classe pour avoir une instance de celle-ci. Elle stocke cette instance dans une variable protégée dans la classe.

Concurrence

Il faudra aussi tenir compte qu’il est possible que plusieurs clients demandent l’instance en même temps. Quand elle a déjà été instanciée cela ne pose pas de problème, mais cela pourrait engendrer des effets de bord lors de la première instanciation.

Structure

Manière dont les parties d’un tout sont arrangées entre elles.

Analogie

La vie de tout les jours.

Un des meilleures exemples dans la vie courante, de l’exploitation du “singleton” est tout simplement celui d’un pays et de son gouvernement. Le pays ne peut avoir qu’un et un seul gouvernement à la fois. Et par symétrie au pourrait dire que le point d’accès globale est lorsque l’on dit “Le gouvernement de X”. Celui-ci identifie l’ensemble du gouvernement et donc le groupe de personnes responsables.

Participant(s)

Classes et Objets entrants en jeu dans le Pattern.

  • La Classe Singleton qui permet d’accéder et d’avoir l’unique instance de la classe par une méthode.

Domaine d’application

Exemple(s) de mise en pratique du Pattern.

  • Lorsque l’on doit avoir une et une seule instance d’une classe ;
  • L’accessibilité doit être sous le contrôle de la classe ;
  • Pour éviter la présence de variables globales à une application ;
  • Cela interdit aux différents clients éventuels d’effectuer l’instanciation de la classe d’une autre manière ;
  • Utiliser par exemple pour récupérer le conteneur d’injection de dépendances qui doit être dans la majorité des cas unique à l’application et instancié, alimenté la première fois.

Fréquence d’utilisation


Note : 3.5 sur 5.

Complexité


Note : 1 sur 5.

Popularité


Note : 3 sur 5.

Représentation UML

Diagramme UML du pattern.

Représentation en Code

Implémentation du Pattern dans différents langages de développement pour démontrer sa mise en pratique.

C#

using System;

namespace DoFactory.GangOfFour.Singleton.Structural
{
  /// <summary>
  /// MainApp startup class for Structural
  /// Singleton Design Pattern.
  /// </summary>

  class MainApp
  {

    /// <summary>
    /// Entry point into console application.
    /// </summary>

    static void Main()
    {
      // Constructor is protected -- cannot use new
      Singleton s1 = Singleton.Instance();
      Singleton s2 = Singleton.Instance();

      // Test for same instance
      if (s1 == s2)
      {
        Console.WriteLine("Objects are the same instance");
      }

     // Wait for user
      Console.ReadKe();
    }
  }

  /// <summary>
  /// The 'Singleton' class
  /// </summary>

  class Singleton
  {
    private static Singleton _instance;

    // Constructor is 'protected'
    protected Singleton()
    {
    }

    public static Singleton Instance()
    {
      // Uses lazy initialization.
      // Note: this is not thread safe.
      if (_instance == null)
      {
        _instance = new Singleton();
      }

      return _instance;

    }
  }
}

Typescript

**
 * The Singleton class defines the `getInstance` method that lets clients access
 * the unique singleton instance.
 */
class Singleton {
    private static instance: Singleton;

    /**
     * The Singleton's constructor should always be private to prevent direct
     * construction calls with the `new` operator.
     */
    private constructor() { }

    /**
     * The static method that controls the access to the singleton instance.
     *
     * This implementation let you subclass the Singleton class while keeping
     * just one instance of each subclass around.
     */
    public static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }

        return Singleton.instance;
    }

    /**
     * Finally, any singleton should define some business logic, which can be
     * executed on its instance.
     */
    public someBusinessLogic() {
        // ...
    }
}

/**
 * The client code.
 */
function clientCode() {
    const s1 = Singleton.getInstance();
    const s2 = Singleton.getInstance();

    if (s1 === s2) {
        console.log('Singleton works, both variables contain the same instance.');
    } else {
        console.log('Singleton failed, variables contain different instances.');
    }
}

clientCode();

Frédéric Schmidt

Lead Technical Architect.

Ajouer un commentaire

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Recent Comments

    %d blogueurs aiment cette page :