logo

Modèle de conception de méthode Singleton

Le modèle Singleton est probablement le modèle de conception le plus largement utilisé. C'est un modèle simple, facile à comprendre et à utiliser. Parfois, il est utilisé de manière excessive et dans des scénarios où il n’est pas nécessaire. Dans de tels cas, les inconvénients de son utilisation l’emportent sur les avantages qu’il apporte. Pour cette raison, le modèle singleton est parfois considéré comme un anti-modèle ou modèle singleton .

Modèle de conception de méthode Singleton



Sujets importants pour le modèle de conception de la méthode Singleton

1. Qu'est-ce que le modèle de conception de la méthode Singleton ?

La méthode Singleton ou Singleton Design Pattern est l’un des modèles de conception les plus simples. Cela garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à celle-ci.

comment convertir un entier en chaîne Java

2. Quand utiliser le modèle de conception de la méthode Singleton ?

Utilisez le modèle de conception de la méthode Singleton lorsque :



  • Il doit y avoir exactement une instance d'une classe et elle doit être accessible aux clients à partir d'un point d'accès bien connu.
  • Lorsque la seule instance doit être extensible par sous-classe et que les clients doivent pouvoir utiliser une instance étendue sans modifier
  • Les classes Singleton sont utilisées pour la journalisation, les objets pilotes, la mise en cache, le pool de threads et les connexions à la base de données.

3. Types d'initialisation de Singleton

La classe Singleton peut être instanciée par deux méthodes :

  • Initialisation anticipée : Dans cette méthode, la classe est initialisée, qu'elle doive être utilisée ou non. Le principal avantage de cette méthode est sa simplicité. Vous lancez la classe au moment du chargement de la classe. Son inconvénient est que la classe est toujours initialisée, qu'elle soit utilisée ou non.
  • Initialisation paresseuse : Dans cette méthode, la classe est initialisée uniquement lorsque cela est nécessaire. Cela peut vous éviter d’instancier la classe lorsque vous n’en avez pas besoin. Généralement, l'initialisation paresseuse est utilisée lorsque nous créons une classe singleton.

4. Composant clé du modèle de conception de la méthode Singleton :

Composant clé du modèle de conception de méthode Singleton (1)

4.1. Membre statique :

Le modèle Singleton ou modèle Singleton emploie un membre statique au sein de la classe. Ce membre statique garantit que la mémoire n'est allouée qu'une seule fois, préservant ainsi l'instance unique de la classe Singleton.



Java
// Static member to hold the single instance private static Singleton instance;>

4.2. Constructeur privé :

Le modèle Singleton ou modèle singleton intègre un constructeur privé, qui sert de barricade contre les tentatives externes de création d'instances de la classe Singleton. Cela garantit que la classe contrôle son processus d’instanciation.

Java
// Private constructor to // prevent external instantiation class Singleton {  // Making the constructor as Private  private Singleton()  {  // Initialization code here  } }>

4.3. Méthode d'usine statique :

Un aspect crucial du modèle Singleton est la présence d’une méthode de fabrique statique. Cette méthode agit comme une passerelle, fournissant un point d'accès global à l'objet Singleton. Lorsqu'une personne demande une instance, cette méthode crée une nouvelle instance (si aucune n'existe) ou renvoie l'instance existante à l'appelant.

Java
// Static factory method for global access public static Singleton getInstance() {  // Check if an instance exists  if (instance == null) {  // If no instance exists, create one  instance = new Singleton();  }  // Return the existing instance  return instance; }>

5. Mise en œuvre du modèle de conception de la méthode Singleton

L'implémentation d'un Singleton Design Pattern ou d'un Pattern Singleton est décrite dans le diagramme de classes suivant :

Capture d'écran-2023-12-07-174635

Implémentation du modèle de conception de la méthode Singleton

L’implémentation du modèle de conception singleton est très simple et consiste en une seule classe. Pour garantir que l'instance singleton est unique, tous les constructeurs singleton doivent être rendus privés. L'accès global se fait via une méthode statique qui peut être accessible globalement à une seule instance, comme indiqué dans le code.

Java
/*package whatever //do not write package name here */ import java.io.*; class Singleton {  // static class  private static Singleton instance;  private Singleton()  {  System.out.println('Singleton is Instantiated.');  }  public static Singleton getInstance()  {  if (instance == null)  instance = new Singleton();  return instance;  }  public static void doSomething()  {  System.out.println('Somethong is Done.');  } } class GFG {  public static void main(String[] args)  {  Singleton.getInstance().doSomething();  } }>

Sortir
Singleton is Instantiated. Somethong is Done.>

La méthode getInstance, on vérifie si l'instance est nulle. Si l'instance n'est pas nulle, cela signifie que l'objet a été créé auparavant ; sinon nous le créons en utilisant l'opérateur new.

6. Différentes façons de mettre en œuvre le modèle de conception de la méthode Singleton

Parfois, nous n'avons besoin que d'une seule instance de notre classe, par exemple une seule connexion à la base de données partagée par plusieurs objets, car la création d'une connexion à la base de données distincte pour chaque objet peut être coûteuse. De même, il peut y avoir un seul gestionnaire de configuration ou un seul gestionnaire d'erreurs dans une application qui gère tous les problèmes au lieu de créer plusieurs gestionnaires.

Implémentation classique

Voyons différentes options de conception pour implémenter une telle classe. Si vous maîtrisez bien les variables de classe statiques et les modificateurs d'accès, cela ne devrait pas être une tâche difficile.

Méthode 1 – Implémentation classique || Rendre getInstance() statique à implémenter Modèle de conception de méthode Singleton

Java
// Classical Java implementation of singleton // design pattern class Singleton {  private static Singleton obj;  // private constructor to force use of  // getInstance() to create Singleton object  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

Ici, nous avons déclaré getInstance() static afin que nous puissions l'appeler sans instancier la classe. La première fois getInstance() est appelé, il crée un nouvel objet singleton et après cela, il renvoie simplement le même objet.

Note: L'objet Singleton n'est pas créé tant que nous n'en avons pas besoin et que nous appelons le getInstance() méthode. C'est ce qu'on appelle l'instanciation paresseuse. Le principal problème avec la méthode ci-dessus est qu’elle n’est pas thread-safe. Considérez la séquence d'exécution suivante.

Cette séquence d'exécution crée deux objets pour le singleton. Par conséquent, cette implémentation classique n’est pas thread-safe.

Méthode 2 || Rendre getInstance() synchronisé pour implémenter Modèle de conception de méthode Singleton

Java
// Thread Synchronized Java implementation of // singleton design pattern class Singleton {  private static Singleton obj;  private Singleton() {}  // Only one thread can execute this at a time  public static synchronized Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

Ici, l'utilisation de synchronisé garantit qu'un seul thread à la fois peut s'exécuter getInstance() . Le principal inconvénient de cette méthode est que l'utilisation de synchronisé à chaque fois lors de la création de l'objet singleton est coûteuse et peut diminuer les performances de votre programme. Cependant, si les performances de getInstance() n'est pas critique pour votre application, cette méthode fournit une solution propre et simple.

Méthode 3 – Instanciation impatiente || Implémentation basée sur un initialiseur statique du modèle de conception singleton

Java
// Static initializer based Java implementation of // singleton design pattern class Singleton {  private static Singleton obj = new Singleton();  private Singleton() {}  public static Singleton getInstance() { return obj; } }>

Ici, nous avons créé une instance d'un singleton dans un initialiseur statique. JVM exécute un initialiseur statique lorsque la classe est chargée, ce qui garantit qu'il est thread-safe. Utilisez cette méthode uniquement lorsque votre classe singleton est légère et est utilisée tout au long de l'exécution de votre programme.

Méthode 4 – La plus efficace || Utiliser le verrouillage à double vérification pour implémenter le modèle de conception singleton

Si vous remarquez attentivement une fois qu'un objet est créé, la synchronisation n'est plus utile car désormais obj ne sera plus nul et toute séquence d'opérations conduira à des résultats cohérents. Nous n’acquerrons donc le verrou sur getInstance() qu’une seule fois lorsque l’obj est nul. De cette façon, nous synchronisons uniquement le premier passage, exactement ce que nous voulons.

Java
// Double Checked Locking based Java implementation of // singleton design pattern class Singleton {  private static volatile Singleton obj = null;  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null) {  // To make thread safe  synchronized (Singleton.class)  {  // check again as multiple threads  // can reach above step  if (obj == null)  obj = new Singleton();  }  }  return obj;  } }>

Nous avons déclaré l'obj volatil ce qui garantit que plusieurs threads proposent correctement la variable obj lors de son initialisation sur l'instance Singleton. Cette méthode réduit considérablement la surcharge liée à l’appel de la méthode synchronisée à chaque fois.

7. Cas d'utilisation de la méthode Pattern Singleton

  • Connexions à la base de données : Dans les applications où la création et la gestion des connexions à la base de données sont une opération coûteuse, un Singleton peut être utilisé pour maintenir une seule connexion à la base de données dans toute l'application.
  • Gestion de la configuration: Lorsque vous disposez de paramètres de configuration globaux auxquels différents composants de l'application doivent accéder, un gestionnaire de configuration Singleton peut fournir un point d'accès unique à ces paramètres.
  • Composants de l'interface graphique : Pour les composants ou contrôleurs d’interface utilisateur graphique (GUI), un Singleton peut aider à gérer l’état et les actions de l’interface utilisateur, en fournissant un point de contrôle unique.
  • Gestionnaires de périphériques : Dans les systèmes embarqués ou les applications interagissant avec des périphériques matériels, un Singleton peut être utilisé pour gérer et contrôler l'accès aux périphériques matériels afin d'éviter les conflits.
  • Service d'impression : Dans les systèmes impliquant l'impression de documents ou de rapports, un service d'impression Singleton peut coordonner et gérer les travaux d'impression, garantissant ainsi une utilisation efficace des ressources d'impression.

8. Avantages du modèle de conception de la méthode Singleton :

  • Résout les collisions de noms : Dans les scénarios où un seul point de contrôle est nécessaire pour éviter les conflits ou les collisions de noms, le modèle Singleton garantit qu'il n'existe qu'une seule instance avec un nom unique.
  • Initialisation impatiente ou paresseuse : Le modèle Singleton prend en charge à la fois l'initialisation rapide (création de l'instance lorsque la classe est chargée) et l'initialisation paresseuse (création de l'instance lorsqu'elle est demandée pour la première fois), offrant une flexibilité basée sur le cas d'utilisation.
  • Sécurité du fil : Des modèles Singleton correctement implémentés peuvent assurer la sécurité des threads, garantissant que l'instance est créée de manière atomique et que plusieurs threads ne créent pas par inadvertance des instances en double.
  • Empreinte mémoire réduite : Dans les applications où la consommation de ressources est critique, le modèle Singleton peut contribuer à réduire l'empreinte mémoire en garantissant qu'il n'y a qu'une seule instance de la classe.

9. Inconvénients du modèle de conception Singleton

  • Difficultés des tests : Étant donné que les singletons introduisent un état global, les tests unitaires peuvent devenir difficiles. Tester un composant isolément peut être plus compliqué s'il repose sur un Singleton, car l'état du Singleton peut affecter le résultat des tests.
  • Problèmes de concurrence : Dans un environnement multithread, des problèmes peuvent survenir liés à la création et à l'initialisation de l'instance Singleton. Si plusieurs threads tentent de créer le Singleton simultanément, cela peut entraîner des conditions de concurrence.
  • Extensibilité limitée : Le modèle Singleton peut rendre le code moins extensible. Si vous décidez ultérieurement que vous avez besoin de plusieurs instances de la classe ou que vous souhaitez modifier la logique d'instanciation, cela peut nécessiter une refactorisation importante.
  • Dépendance globale : Le modèle Singleton crée une dépendance globale, ce qui rend plus difficile le remplacement du Singleton par une implémentation alternative ou l'utilisation de l'injection de dépendances pour fournir des instances.
  • Difficile de sous-classer : Sous-classer un Singleton peut être difficile. Étant donné que le constructeur est généralement privé, l'extension d'un Singleton nécessite des soins supplémentaires et peut ne pas suivre les modèles d'héritage standard.
  • La gestion du cycle de vie: Le modèle Singleton peut ne pas gérer les scénarios dans lesquels l'instance doit être explicitement détruite ou réinitialisée. La gestion du cycle de vie du Singleton peut devenir une préoccupation.
  • Abus des points d'accès mondiaux : Même si un point d’accès mondial constitue un avantage, il peut également être utilisé à mauvais escient. Les développeurs pourraient être tentés d'utiliser Singleton pour tout, ce qui entraînerait une utilisation excessive de l'état global et une conception moins modulaire.

10. Conclusion

Il est important que certaines classes n’aient qu’une seule instance. Même s'il peut y avoir plusieurs imprimantes dans un système, il ne doit y avoir qu'un seul spouleur d'imprimante. Il ne devrait y avoir qu'un seul système de fichiers et un seul gestionnaire de fenêtres. Un filtre numérique aura un convertisseur A/D. Un système comptable sera dédié au service d’une entreprise. Comment s’assurer qu’une classe n’a qu’une seule instance et que l’instance est facilement accessible ? Une variable globale rend un objet accessible, mais elle ne vous empêche pas d'instancier plusieurs objets.

Une meilleure solution consiste à rendre la classe elle-même responsable du suivi de sa seule instance. La classe peut garantir qu'aucune autre instance ne peut être créée (en interceptant les demandes de création de nouveaux objets) et elle peut fournir un moyen d'accéder à l'instance. C'est le modèle Singleton.