Pourquoi utiliser un singleton au lieu de méthodes statiques?

93

Je n'ai jamais trouvé de bonnes réponses à ces questions simples sur les classes d'assistance / utilitaire:

Pourquoi créerais-je un singleton (sans état) au lieu d'utiliser des méthodes statiques?

Pourquoi une instance d'objet serait-elle nécessaire si un objet n'a pas d'état?

Sébastien Lorber
la source
duplication possible de stackoverflow.com/questions/720744/static-class-and-singleton
Michael Borgwardt
Ne pensez pas puisque nous parlons de 2 langues différentes donc la réponse peut varier, mais merci pour le lien, en java jamais entendu le terme "monostate"
Sebastien Lorber

Réponses:

79

Souvent, les singletons sont utilisés pour introduire une sorte d' état global dans une application. (Plus souvent que vraiment nécessaire, pour être honnête, mais c'est un sujet pour une autre fois.)

Cependant, il existe quelques cas secondaires où même un singleton sans état peut être utile:

  • Vous prévoyez de l'étendre avec l'état dans un avenir prévisible.
  • Vous avez besoin d'une instance d'objet pour une raison technique particulière .
    Exemple: objets de synchronisation pour le C # lockou l' synchronizedinstruction Java .
  • Vous avez besoin d'héritage, c'est-à-dire que vous voulez pouvoir remplacer facilement votre singleton par un autre en utilisant la même interface mais une implémentation différente.
    Exemple: La Toolkit.getDefaultToolkit()méthode en Java retournera un singleton dont le type exact dépend du système.
  • Vous voulez une égalité de référence pour une valeur sentinelle .
    Exemple: DBNull.Valueen C #.
Heinzi
la source
27
Je vais aller avec +1, bien que les singletons IMHO soient mal utilisés pour introduire des États mondiaux. Le but d'un singleton n'est pas de rendre un objet disponible globalement, mais de faire en sorte qu'un objet ne soit instancié qu'une seule fois. Les objets globaux sont un mal nécessaire. À moins que cela ne soit vraiment nécessaire, il faut essayer de ne pas les utiliser, car ils conduisent généralement à un couplage élevé, avec SomeSingleton.getInstance (). SomeMethod () partout. :)
back2dos
Cela peut être utile dans les jeux où vous ne voulez qu'une seule instance de rendu au lieu de plusieurs instances de rendu, ou avec une classe de canalisation réseau où vous configurez un canal sécurisé pour qu'il ne puisse y avoir qu'une seule connexion à la fois.
Tschallacka
2
"remplacez facilement votre singleton" est le point le plus important de mon point de vue. Le repos est assez proche de l'implémentation de classe statique.
Teoman shipahi
1
Les singletons sont des valeurs sentinelles non nulles utiles pour les types somme / produit et autres. Par exemple, étant la valeur Aucun / Rien dans un type Option ou la valeur Vide pour un type de collection. Vous obtenez des tests rapides Aucun / Vide en prime, car l'égalité des références est tout ce dont vous avez besoin.
itsbruce
@itsbruce: Vos exemples ne sont pas des singletons : la liste vide n'est pas la seule instance possible de la classe List, et la valeur None n'est pas la seule instance possible de la classe Option. Cependant, il y a des exemples où les valeurs sentinelles sont des singletons, et j'ai pris la liberté d'en ajouter un à ma réponse. Merci pour l'input!
Heinzi
37

Je pourrais voir un cas pour un singleton sans état utilisé au lieu d'une classe de méthodes statiques, à savoir pour l' injection de dépendances .

Si vous avez une classe d'assistance de fonctions utilitaires que vous utilisez directement, cela crée une dépendance cachée; vous n'avez aucun contrôle sur qui peut l'utiliser, ni où. L'injection de cette même classe d'assistance via une instance de singleton sans état vous permet de contrôler où et comment elle est utilisée, et de la remplacer / la simuler / etc. lorsque vous en avez besoin.

En faire une instance singleton garantit simplement que vous n'allouez pas plus d'objets du type que nécessaire (puisque vous n'en avez besoin que d'un seul).

Tzaman
la source
1
"vous n'avez aucun contrôle sur qui peut l'utiliser, ou où." Pourquoi quelqu'un en aurait-il besoin?
hagrawal
1
@hagrawal à des fins de test, vous devriez pouvoir vous en moquer
Jemshit Iskenderov
15

En fait, j'ai trouvé une autre réponse non mentionnée ici: les méthodes statiques sont plus difficiles à tester.

Il semble que la plupart des frameworks de test fonctionnent très bien pour les méthodes d'instance simulées, mais beaucoup d'entre eux ne gèrent pas de manière décente la simulation des méthodes statiques.

Sébastien Lorber
la source
2
Mais Powermock semble être en mesure de le faire
Sebastien Lorber
6

Dans la plupart des langages de programmation, les classes échappent à une grande partie du système de types. Alors qu'une classe, avec ses méthodes et variables statiques est un objet, elle ne peut très souvent pas implémenter une interface ou étendre d'autres classes. Pour cette raison, il ne peut pas être utilisé de manière polymorphe, car il ne peut pas être le sous-type d'un autre type. Par exemple, si vous avez une interface IFooable, qui est requise par plusieurs signatures de méthode d'autres classes, l'objet de classe ne StaticFoopeut pas être utilisé à la place de IFooable, alors que FooSingleton.getInstance()can (en supposant, FooSingletonimplémente IFooable).

Veuillez noter que, comme je l'ai commenté sur la réponse de Heinzi, un singleton est un modèle pour contrôler l'instanciation. Il remplace new Class()par Class.getInstance(), ce qui donne à l'auteur Classplus de contrôle sur les instances, qu'il peut utiliser pour empêcher la création d'instances inutiles. Le singleton est juste un cas très particulier du motif de fabrique et doit être traité comme tel. L'utilisation courante en fait plutôt le cas particulier des registres globaux, qui finissent souvent par être mauvais, car les registres globaux ne doivent pas être utilisés bon gré mal gré.

Si vous prévoyez de fournir des fonctions d'assistance globales, les méthodes statiques fonctionneront parfaitement. La classe n'agira pas en tant que classe, mais simplement en tant qu'espace de noms. Je suggère que vous préserviez une cohésion élevée, ou vous pourriez vous retrouver avec les problèmes de couplage les plus étranges.

Greetz
back2dos

back2dos
la source
4

Il y a un compromis entre utiliser lequel. Les singletons peuvent avoir ou non un état et ils se réfèrent à des objets. S'ils ne conservent pas l'état et ne sont utilisés que pour un accès global, alors la statique est préférable car ces méthodes seront plus rapides. Mais si vous souhaitez utiliser des objets et des concepts POO (polymorphisme d'héritage), alors le singleton est meilleur.

Prenons un exemple: java.lang.Runtime est une classe singleton en java. Cette classe autorise différentes implémentations pour chaque JVM. L'implémentation est unique par JVM. Si cette classe aurait été statique, nous ne pouvons pas transmettre différentes implémentations basées sur JVM.

J'ai trouvé ce lien vraiment utile: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

J'espère que ça aide!!

Atihska
la source
Cette réponse est bonne pour inclure un exemple concret dans le monde réel.
systemovich
2

Pour moi "Want Object State use Singleton, Want Function use static method"

Cela dépend de ce que vous voulez. Chaque fois que vous voulez l'état de l'objet (par exemple, Polymorphisme comme l'état Null au lieu de null, ou l'état par défaut), singleton est le choix approprié pour vous tandis que la méthode statique est utilisée lorsque vous avez besoin d'une fonction (recevoir des entrées puis renvoyer une sortie).

Je recommande pour le cas singleton, il devrait toujours avoir le même état après son instanciation. Il ne doit ni être clonable, ni recevoir de valeur à définir (sauf la configuration statique du fichier, par exemple le fichier de propriétés en java).

PS Les performances entre ces 2 sont différentes en millisecondes, alors concentrez-vous d'abord sur l' architecture .

Toomtarm Kung
la source
1

Singleton n'est pas apatride, il détient l'état global.

Certaines raisons pour lesquelles je peux penser à utiliser Singleton sont:

  • Pour éviter les fuites de mémoire
  • Pour fournir le même état pour tous les modules d'une application, par exemple une connexion à la base de données
Indigo Praveen
la source
Je sais mais en fait un singleton peut plus ou moins être apatride ... S'il ne partage aucun attribut de classe ...
Sebastien Lorber