
Qu'est-ce qu'un singleton en Java ?
Singleton est l'un des modèles de conception les plus simples au niveau de la classe. Parfois, les gens disent "cette classe est singleton", ce qui signifie que la classe implémente le modèle de conception singleton. Parfois, il est nécessaire d'écrire une classe où nous restreignons l'instanciation à un seul objet. Par exemple, une classe responsable de la journalisation ou de la connexion à un base de données. Le modèle de conception singleton décrit comment nous pouvons y parvenir. Un singleton est un modèle de conception qui fait deux choses :-
Il garantit qu'il n'y aura jamais qu'une seule instance de la classe.
-
Il fournit un point d'accès global unique à cette instance.
-
Un constructeur privé. Cela limite la possibilité de créer des objets de la classe en dehors de la classe elle-même.
-
Une méthode statique publique qui renvoie l'instance de la classe. Cette méthode s'appelle getInstance . C'est le point d'accès global à l'instance de classe.
Options de mise en œuvre
Le modèle de conception singleton est appliqué de différentes manières. Chaque option est bonne et mauvaise à sa manière. Comme toujours, il n'y a pas d'option parfaite ici, mais nous devrions nous efforcer d'en trouver une. Tout d'abord, décidons de ce qui constitue le bien et le mal, et quelles mesures affectent la façon dont nous évaluons les différentes implémentations du modèle de conception. Commençons par le bon. Voici les facteurs qui rendent une mise en œuvre plus juteuse et attrayante :-
Initialisation différée : l'instance n'est pas créée tant qu'elle n'est pas nécessaire.
-
Code simple et transparent : cette métrique, bien sûr, est subjective, mais elle est importante.
-
Thread safety : bon fonctionnement dans un environnement multi-thread.
-
Hautes performances dans un environnement multi-thread : peu ou pas de blocage de thread lors du partage d'une ressource.
-
Pas d'initialisation paresseuse : lorsque la classe est chargée au démarrage de l'application, qu'elle soit nécessaire ou non (paradoxalement, dans le monde informatique il vaut mieux être paresseux)
-
Code complexe et difficile à lire. Cette mesure est également subjective. Si vos yeux commencent à saigner, nous supposerons que la mise en œuvre n'est pas la meilleure.
-
Manque de sécurité des fils. En d'autres termes, "danger de fil". Opération incorrecte dans un environnement multithread.
-
Performances médiocres dans un environnement multi-thread : les threads se bloquent tout le temps ou souvent lors du partage d'une ressource.
Code
Nous sommes maintenant prêts à envisager diverses options de mise en œuvre et à indiquer les avantages et les inconvénients :Simple
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
La mise en œuvre la plus simple. Avantages:
-
Code simple et transparent
-
Sécurité des fils
-
Hautes performances dans un environnement multithread
- Pas d'initialisation paresseuse.
Initialisation paresseuse
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Avantages:
-
Initialisation paresseuse.
-
Non thread-safe
Accès synchronisé
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Avantages:
-
Initialisation paresseuse.
-
Sécurité des fils
-
Mauvaise performance multithread
Verrouillage à double contrôle
public class Singleton {
private static final Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
Avantages:
-
Initialisation paresseuse.
-
Sécurité des fils
-
Hautes performances dans un environnement multithread
-
Non pris en charge dans les versions antérieures de Java inférieures à 1.5 (l'utilisation du mot-clé volatile est corrigée depuis la version 1.5)
Titulaire de la classe
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
Avantages:
-
Initialisation paresseuse.
-
Sécurité des fils.
-
Hautes performances dans un environnement multithread.
-
Un fonctionnement correct nécessite une garantie que l' objet singleton est initialisé sans erreur. Sinon, le premier appel à la méthode getInstance entraînera une ExceptionInInitializerError , et tous les appels suivants produiront une NoClassDefFoundError .
Mise en œuvre | Initialisation paresseuse | Sécurité des fils | Performances multithread | Quand utiliser? |
---|---|---|---|---|
Simple | - | + | Rapide | Jamais. Ou éventuellement lorsque l'initialisation paresseuse n'est pas importante. Mais ce ne serait jamais mieux. |
Initialisation paresseuse | + | - | N'est pas applicable | Toujours lorsque le multithreading n'est pas nécessaire |
Accès synchronisé | + | + | Lent | Jamais. Ou peut-être lorsque les performances multithread n'ont pas d'importance. Mais ce ne serait jamais mieux. |
Verrouillage à double contrôle | + | + | Rapide | Dans de rares cas où vous devez gérer des exceptions lors de la création du singleton (lorsque le singleton du détenteur de la classe n'est pas applicable) |
Titulaire de la classe | + | + | Rapide | Chaque fois que le multithreading est nécessaire et qu'il est garanti que l'objet singleton sera créé sans problème. |
Avantages et inconvénients du modèle singleton
En général, un singleton fait exactement ce qu'on attend de lui :-
Il garantit qu'il n'y aura jamais qu'une seule instance de la classe.
-
Il fournit un point d'accès global unique à cette instance.
-
Un singleton viole le principe de responsabilité unique : en plus de ses fonctions directes, la classe singleton contrôle également le nombre d'instances.
-
La dépendance d'une classe ordinaire à un singleton n'est pas visible dans le contrat public de la classe.
-
Les variables globales sont mauvaises. En fin de compte, un singleton se transforme en une variable globale lourde.
-
La présence d'un singleton réduit la testabilité de l'application dans son ensemble et des classes qui utilisent le singleton en particulier.
GO TO FULL VERSION