Singleton
Concept du Singleton
Un singleton est une classe qui ne peut être instanciée qu'une seule fois. Les exemples classiques de singletons incluent les objets sans état ou les composants système uniques. Cependant, les classes singleton posent un problème de testabilité, notamment lorsqu'elles ne sont pas définies via une interface avec une implémentation séparée.
Méthodes de création d'un Singleton
Membre public static qui est un champ final
Le constructeur privé n'est appelé qu'une seule fois lors de l'initialisation de l'instance Elvis, garantissant ainsi qu'il s'agit de la seule instance dans l'ensemble du système. Cependant, il est possible d'utiliser AccessibleObject.setAccessible() pour appeler le constructeur privé. Cette méthode de modification via la réflexion peut être bloquée en lançant une exception lors de la création du deuxième objet.
- Avantages
- Le fait que la classe soit un singleton est clairement indiqué dans l'API.
- Concis.
Méthode d'usine statique publique
À part la modification via la réflexion, cette méthode garantit également qu'il s'agit de la seule instance dans l'ensemble du système. La seule différence est que le champ est devenu privé et que la méthode d'usine statique est utilisée pour renvoyer l'objet.
- Avantages
- Il est possible de modifier la classe en une classe non-singleton sans modifier l'API.
- Par exemple, la méthode d'usine statique peut renvoyer une instance différente pour chaque thread.
- Si nécessaire, il est possible de modifier la méthode d'usine en une méthode d'usine de singleton générique.
- La référence à la méthode de l'usine statique peut être utilisée comme fournisseur.
- Par exemple, Elvis::getInstance peut être utilisé à la place de Supplier<Elvis>.
- Il est possible de modifier la classe en une classe non-singleton sans modifier l'API.
Si vous n'avez pas besoin d'utiliser les avantages ci-dessus, il est préférable d'utiliser la première méthode.
Utilisation d'un type d'énumération
La méthode la plus recommandée est d'utiliser un type d'énumération. Comparé aux deux méthodes ci-dessus, il est plus sûr contre les attaques par réflexion et le code est plus propre. De plus, comme expliqué plus loin, les deux méthodes ci-dessus présentent l'inconvénient de devoir ajouter du code supplémentaire lors de la sérialisation.
Cependant, il est important de noter que si le singleton que vous souhaitez créer hérite d'une interface, il ne peut pas hériter d'une classe.
Points à prendre en compte lors de la sérialisation d'une classe Singleton
Si vous souhaitez sérialiser une classe Singleton créée avec la première ou la deuxième méthode, vous devez non seulement implémenter Serializable, mais également déclarer tous les champs d'instance comme transient et redéfinir la méthode readResolve().
Commentaires0