web-dev-qa-db-fra.com

Quand utiliser un Singleton et quand utiliser une classe statique

J'ai cherché à ce sujet ici et sur StackOverflow et j'ai trouvé des différences entre les deux.

Mais je ne suis toujours pas sûr dans quels cas on préférerait un Singleton, et dans quels cas on choisirait d'utiliser une classe statique.

(Dans les langages qui ne prennent pas en charge les "classes statiques", comme Java, je fais évidemment référence aux classes contenant uniquement des méthodes et des champs statiques).

Veuillez me donner des exemples concrets de cas où vous choisiriez chacun d'eux, et expliquez pourquoi.

34
Aviv Cohn

Un cas où une classe statique peut être une bonne idée est lorsque vous souhaitez collecter des éléments de fonctionnalité associés, mais que vous n'avez pas besoin d'avoir d'état interne dans un objet. Un exemple pourrait être la classe Math en Java. Il contient tout un tas de fonctions connexes accessibles en dehors du contexte d'une instance d'objet spécifique. J'ai fait des choses similaires où un ensemble de fonctions utilitaires communes qui sont utilisées à plusieurs endroits dans une application sont regroupées dans une seule classe utilitaire.

Un singleton est utilisé lorsque vous faites voulez un objet réel (avec son propre état interne et tout), et que vous voulez limiter votre système à exactement ne instance de cet objet. Cela peut être utile si vous avez une sorte de ressource partagée, telle qu'une base de données, un cache en mémoire ou peut-être un matériel spécialisé comme un bras robotique. De nombreuses parties de votre programme peuvent vouloir utiliser cette ressource et vous pouvez souhaiter que tous les accès à la ressource passent par un seul point. Un singleton n'est pas toujours la seulement façon de gérer ces situations, mais c'est l'un des rares endroits où je pense qu'un singleton pourrait être un bon choix.

  • Évitez le modèle Gang of Four Singleton, pour les raisons citées dans les autres réponses. Il s'agit principalement d'un anti-modèle basé sur les difficultés qu'il crée pour les tests.

  • L'injection d'usine et de dépendance a rendu Singleton obsolète. La meilleure réponse est d'utiliser une Factory qui décide d'instancier une ou plusieurs instances d'une classe donnée. De cette façon, la classe et ses clients ne sont pas responsables de son statut de singleton - cela devient une préoccupation transparente gérée par l'usine.

  • Les frameworks d'injection de dépendances comme Spring font cela pour vous dès le départ (par exemple, les beans Spring sont des singletons, sauf indication contraire).

  • Les classes purement statiques sont problématiques à la fois pour tester et utiliser OO concepts. J'ai vu des équipes avec une irrésistible envie de rendre tout statique et final, et la question devient, pourquoi n'écrivent-ils pas simplement du code C?

  • Si votre classe statique a des effets secondaires, elle ne doit pas être statique. Cela signifie que s'il gère l'état partagé ou s'il modifie l'état des paramètres, il doit s'agir d'une classe régulière dans laquelle Factory distribue une seule instance partagée. Une classe purement statique qui gère l'état partagé devient un problème vraiment difficile à tester.

  • Une classe purement statique crée également des dépendances dures à la compilation sur cette classe particulière, ce qui compromet vraiment la capacité d'extension et la capacité de test de votre code. On dirait que vous voudriez réserver cela à quelque chose d'éternel et immuable, sans effets secondaires, comme des formules mathématiques.

Donc, la réponse est, n'écrivez pas les classes en singletons, mais déplacez plutôt cette décision dans votre usine. Et dans un langage OO, les classes statiques manquent certains des aspects de conception les plus importants du langage et compliquent les tests. Encore une fois, vous pouvez utiliser des classes de travail avec une sémantique spécifique pour les regrouper et les faire générer par votre usine.

12
Rob

Objets singletons créés de sorte qu'il ne peut y avoir qu'une seule instance à un moment donné et peuvent être utilisés à l'échelle de l'application.

Les objets qui gèrent des trucs comme les pools de connexions sont un bon candidat pour être Singletons;

  • Vous ne voulez qu'une seule instance dans toute l'application
  • vous devez pouvoir y accéder à partir de différentes parties de l'application
  • les données qu'il contient doivent être conservées même si aucun autre objet ne pointe actuellement dessus (pratique lorsque vous souhaitez réutiliser des objets coûteux à initialiser).

Une classe remplie uniquement de méthodes statiques n'est pas quelque chose qui est généralement destiné à être initialisé comme un objet. Cela ressemble plus à un wrapper pour les méthodes statiques qu'il contient.

Un exemple de cela que j'utilise fréquemment est une classe utilitaire avec des méthodes qui effectuent des tâches répétitives qui prennent des paramètres, fait un calcul avec elles/les formate/etc. et renvoie ensuite le résultat, sans utiliser de champs ou de méthodes externes (ou du moins pas non statiques). Je n'initialise jamais une classe utilitaire, j'utilise juste les méthodes statiques pour toutes les méthodes répétitives.

C'est juste ainsi que j'ai tendance à utiliser des singletons et des classes statiques (remplies de méthodes), je ne sais pas si cela confirme les normes "officielles" ...

0
Rob