J'ai lu qu'il est possible de mettre Singleton
en œuvre en Java en utilisant un Enum
tel que:
public enum MySingleton {
INSTANCE;
}
Mais comment cela fonctionne-t-il? Plus précisément, un Object
doit être instancié. Ici, comment l' MySingleton
instanciation? Qui fait new MySingleton()
?
INSTANCE
est le même quepublic static final MySingleton INSTANCE = new MySingleton();
.Réponses:
Ce,
a un constructeur vide implicite. Rendez-le plutôt explicite,
Si vous avez ensuite ajouté une autre classe avec une
main()
méthode commeTu verrais
enum
Les champs sont des constantes de temps de compilation, mais ce sont des instances de leurenum
type. Et, ils sont construits lorsque le type enum est référencé pour la première fois .la source
private
modificateur n'a aucune signification pour unenum
constructeur et est entièrement redondant.Un
enum
type est un type spécial declass
.Votre
enum
sera en fait compilé en quelque chose commeLorsque votre code accède pour la première fois
INSTANCE
, la classeMySingleton
est chargée et initialisée par la JVM. Ce processus initialise lestatic
champ ci-dessus une fois (paresseusement).la source
public enum MySingleton { INSTANCE,INSTANCE1; }
puisSystem.out.println(MySingleton.INSTANCE.hashCode()); System.out.println(MySingleton.INSTANCE1.hashCode());
il imprime différents hashcodes. Cela signifie-t-il que deux objets de MySingleton sont créés?enum
constantes de différence .Dans ce livre de bonnes pratiques Java de Joshua Bloch, vous pouvez découvrir pourquoi vous devez appliquer la propriété Singleton avec un constructeur privé ou un type Enum. Le chapitre est assez long, alors gardez-le résumé:
Faire d'une classe un singleton peut rendre difficile le test de ses clients, car il est impossible de remplacer une implémentation fictive pour un singleton à moins qu'il n'implémente une interface qui lui sert de type. L'approche recommandée consiste à implémenter des singletons en créant simplement un type enum avec un élément:
Cette approche est fonctionnellement équivalente à l'approche du champ public, sauf qu'elle est plus concise, fournit gratuitement la machinerie de sérialisation et offre une garantie absolue contre l'instanciation multiple, même face à des attaques de sérialisation ou de réflexion sophistiquées.
la source
Comme toutes les instances enum, Java instancie chaque objet lorsque la classe est chargée, avec une certaine garantie qu'elle est instanciée exactement une fois par JVM . Considérez la
INSTANCE
déclaration comme un champ final statique public: Java instanciera l'objet la première fois que la classe sera référencée.Les instances sont créées lors de l'initialisation statique, qui est définie dans la spécification du langage Java, section 12.4 .
Pour ce que cela vaut, Joshua Bloch décrit ce modèle en détail comme l'élément 3 de Effective Java Second Edition .
la source
Puisque Singleton Pattern consiste à avoir un constructeur privé et à appeler une méthode pour contrôler les instanciations (comme certaines
getInstance
), dans Enums, nous avons déjà un constructeur privé implicite.Je ne sais pas exactement comment la JVM ou un conteneur contrôle les instances de notre
Enums
, mais il semble qu'il utilise déjà un impliciteSingleton Pattern
, la différence est que nous n'appelons pas agetInstance
, nous appelons simplement Enum.la source
Comme cela a, dans une certaine mesure, été mentionné précédemment, une enum est une classe java avec la condition spéciale que sa définition doit commencer par au moins une "constante enum".
En dehors de cela, et que les énumérations ne peuvent pas être étendues ou utilisées pour étendre d'autres classes, une énumération est une classe comme n'importe quelle classe et vous l'utilisez en ajoutant des méthodes sous les définitions de constante:
Vous accédez aux méthodes du singleton en suivant ces lignes:
L'utilisation d'une énumération, au lieu d'une classe, est, comme cela a été mentionné dans d'autres réponses, principalement sur une instanciation thread-safe du singleton et une garantie qu'il ne sera toujours qu'une copie.
Et, peut-être, plus important encore, que ce comportement est garanti par la machine virtuelle Java elle-même et la spécification Java.
Voici une section de la spécification Java sur la façon dont plusieurs instances d'une instance enum sont empêchées:
Il convient de noter qu'après l'instanciation, tout problème de sécurité des threads doit être traité comme dans toute autre classe avec le mot-clé synchronized, etc.
la source