Avouons-le. Le motif Singleton est un sujet très controversé avec des hordes de programmeurs des deux côtés de la clôture. Il y a ceux qui pensent que le Singleton n'est rien de plus qu'une variable globale glorifiée, et d'autres qui ne jurent que par le modèle et l'utilisent sans cesse. Cependant, je ne veux pas que la controverse sur Singleton soit au cœur de ma question. Tout le monde peut avoir un bras de fer et se battre et voir qui gagne pour tout ce que je tiens . Ce que j'essaie de dire, c'est que je ne crois pas qu'il y ait une seule bonne réponse et je n'essaie pas intentionnellement d'attiser les querelles partisanes. Je suis simplement intéressé par les alternatives singleton lorsque je pose la question:
Existe-t-il des alternatives spécifiques au GOF Singleton Pattern?
Par exemple, plusieurs fois lorsque j'ai utilisé le modèle singleton dans le passé, je suis simplement intéressé par la préservation de l'état / des valeurs d'une ou plusieurs variables. L'état / les valeurs des variables, cependant, peuvent être conservés entre chaque instanciation de la classe en utilisant des variables statiques au lieu d'utiliser le modèle singleton.
Quelle autre idée avez-vous?
EDIT: Je ne veux pas vraiment que ce soit un autre article sur «comment utiliser correctement le singleton». Encore une fois, je cherche des moyens de l'éviter. Pour le plaisir, d'accord? Je suppose que je pose une question purement académique dans votre meilleure voix de bande-annonce: "Dans un univers parallèle où il n'y a pas de singleton, que pourrions-nous faire?"
la source
Réponses:
Alex Miller dans " Patterns I Hate " cite ce qui suit:
"Quand un singleton semble être la réponse, je trouve qu'il est souvent plus sage de:
la source
Pour comprendre la bonne façon de contourner les Singletons, vous devez comprendre ce qui ne va pas avec les Singletons (et l'état global en général):
Les singletons cachent les dépendances.
Pourquoi est-ce important?
Parce que si vous masquez les dépendances, vous avez tendance à perdre la trace de la quantité de couplage.
Vous pourriez dire que
est plus simple que
mais au moins la deuxième API indique clairement quels sont les collaborateurs de la méthode.
Ainsi, le moyen de contourner les singletons n'est pas d'utiliser des variables statiques ou des localisateurs de services, mais de changer les classes Singleton en instances, qui sont instanciées dans la portée où elles ont un sens et injectées dans les composants et les méthodes qui en ont besoin. Vous pouvez utiliser un framework IoC pour gérer cela, ou vous pouvez le faire manuellement, mais l'important est de vous débarrasser de votre état global et de rendre les dépendances et les collaborations explicites.
la source
La meilleure solution que j'ai trouvée consiste à utiliser le modèle d'usine pour construire des instances de vos classes. En utilisant le modèle, vous pouvez vous assurer qu'il n'y a qu'une seule instance d'une classe partagée entre les objets qui l'utilisent.
Je pensais que ce serait compliqué à gérer, mais après avoir lu ce billet de blog "Where Have All the Singletons Gone?" , cela semble si naturel. Et en passant, cela aide beaucoup à isoler vos tests unitaires.
En résumé, que devez-vous faire? Chaque fois qu'un objet dépend d'un autre, il en recevra une instance uniquement via son constructeur (pas de nouveau mot-clé dans votre classe).
Et puis, l'usine.
Comme vous n'instancierez votre fabrique qu'une seule fois, il y aura une seule instanciation d'exSingleton. Chaque fois que vous appelez buildNeedy, la nouvelle instance de NeedyClass sera fournie avec exSingleton.
J'espère que ça aide. Veuillez signaler toute erreur.
la source
Spring ou tout autre conteneur IoC fait un assez bon travail à cet égard. Étant donné que les classes sont créées et gérées en dehors de l'application elle-même, le conteneur peut créer des singletons de classes simples et les injecter si nécessaire.
la source
Vous ne devriez pas avoir à vous mettre en quatre pour éviter tout schéma. L'utilisation d'un motif est soit une décision de conception, soit un ajustement naturel (il se met simplement en place). Lorsque vous concevez un système, vous avez le choix d'utiliser un modèle ou de ne pas l'utiliser. Cependant, vous ne devriez pas faire tout votre possible pour éviter tout ce qui est finalement un choix de conception.
Je n'évite pas le modèle Singleton. Soit c'est approprié et je l'utilise, soit ce n'est pas approprié et je ne l'utilise pas. Je pense que c'est aussi simple que cela.
La pertinence (ou son absence) du Singleton dépend de la situation. C'est une décision de conception qui doit être prise et les conséquences de cette décision doivent être comprises (et documentées).
la source
Monostate (décrit dans Agile Software Development de Robert C. Martin) est une alternative au singleton. Dans ce modèle, les données de la classe sont toutes statiques mais les getters / setters ne sont pas statiques.
Par exemple:
Monostate a un comportement similaire à singleton mais le fait d'une manière où le programmeur n'est pas nécessairement conscient du fait qu'un singleton est utilisé.
la source
Le modèle singleton existe car il existe des situations dans lesquelles un seul objet est nécessaire pour fournir un ensemble de services .
Même si c'est le cas, je considère toujours l'approche de création de singletons en utilisant un champ / propriété statique global représentant l'instance, inappropriée. C'est inapproprié car cela crée une dépendance dans le code entre le champ statique et l'objet non, les services fournis par l'objet.
Donc, au lieu du modèle classique, singleton, je recommande d'utiliser le modèle de service `` comme '' avec des conteneurs desservis , où au lieu d'utiliser votre singleton via un champ statique, vous obtenez une référence à celui-ci via une méthode demandant le type de service requis.
au lieu d'un seul global
De cette façon, lorsque vous voulez changer le type d'un objet de singleton à autre chose, vous aurez du temps à le faire. De plus, comme avantage supplémentaire, vous n'avez pas à transmettre une part d'instances d'objet à chaque méthode.
Voir également Inversion de contrôle , l'idée est qu'en exposant des singletons directement au consommateur, vous créez une dépendance entre le consommateur et l'instance d'objet, et non les services d'objet fournis par l'objet.
Mon avis est de masquer l'utilisation du motif singleton chaque fois que cela est possible, car il n'est pas toujours possible de l'éviter, ou souhaitable.
la source
Si vous utilisez un Singleton pour représenter un seul objet de données, vous pouvez plutôt passer un objet de données en tant que paramètre de méthode.
(bien que, je dirais que c'est la mauvaise façon d'utiliser un Singleton en premier lieu)
la source
Si votre problème est que vous souhaitez conserver l'état, vous voulez une classe MumbleManager. Avant de commencer à travailler avec un système, votre client crée un MumbleManager, où Mumble est le nom du système. L'État est conservé à travers cela. Il y a de fortes chances que votre MumbleManager contienne un sac de propriétés qui contient votre état.
Ce type de style ressemble beaucoup à C et pas très à un objet - vous constaterez que les objets qui définissent votre système auront tous une référence au même MumbleManager.
la source
Utilisez un objet simple et un objet usine. La fabrique est responsable de la réglementation de l'instance et des détails de l'objet simple uniquement avec les informations de configuration (qu'elle contient par exemple) et le comportement.
la source
En fait, si vous concevez à partir de zéro en évitant les singeltons, vous n'aurez peut-être pas à contourner le fait de ne pas utiliser de singletons en utilisant des variables statiques. Lorsque vous utilisez des variables statiques, vous créez également plus ou moins un Singleton, la seule différence est que vous créez différentes instances d'objet, mais en interne, elles se comportent toutes comme si elles utilisaient un Singleton.
Pouvez-vous peut-être donner un exemple détaillé où vous utilisez un Singleton ou où un Singleton est actuellement utilisé et que vous essayez d'éviter de l'utiliser? Cela pourrait aider les gens à trouver une solution plus sophistiquée sur la façon dont la situation pourrait être gérée sans Singleton du tout.
BTW, je n'ai personnellement aucun problème avec les Singletons et je ne peux pas comprendre les problèmes que les autres ont concernant les Singletons. Je ne vois rien de mal à leur sujet. Autrement dit, si vous n'en abusez pas. Toute technique utile peut être abusée et si elle est abusée, cela conduira à des résultats négatifs. L'héritage est une autre technique couramment utilisée à mauvais escient. Personne ne dirait toujours que l'héritage est quelque chose de mauvais simplement parce que certaines personnes en abusent horriblement.
la source
Personnellement, pour moi, un moyen beaucoup plus judicieux d'implémenter quelque chose qui se comporte comme singleton est d'utiliser une classe entièrement statique (membres statiques, méthodes statiques, propriétés statiques). La plupart du temps, je l'implémente de cette manière (je ne peux penser à aucune différence de comportement du point de vue de l'utilisateur)
la source
Je pense que le meilleur endroit pour contrôler le singleton est au niveau de la conception de la classe. À ce stade, vous devriez être en mesure de cartographier les interactions entre les classes et voir si quelque chose exige absolument qu'une seule instance de cette classe existe à tout moment de la vie des applications.
Si tel est le cas, alors vous avez un singleton. Si vous lancez des singletons pour plus de commodité pendant le codage, vous devriez vraiment revoir votre conception et arrêter de coder lesdits singletons :)
Et oui, «police» est le mot que je voulais dire ici plutôt que «éviter». Le singleton n'est pas quelque chose à éviter (de la même manière que goto et les variables globales ne sont pas quelque chose à éviter). Au lieu de cela, vous devriez surveiller son utilisation et vous assurer que c'est la meilleure méthode pour faire ce que vous voulez de manière efficace.
la source
J'utilise singleton principalement comme "conteneur de méthodes", sans aucun état. Si j'ai besoin de partager ces méthodes avec de nombreuses classes et que je veux éviter le fardeau de l'instanciation et de l'initialisation, je crée un contexte / session et j'initialise toutes les classes là-bas; tout ce qui fait référence à la session a également accès au "singleton" ainsi contenu.
la source
N'ayant pas programmé dans un environnement intensément orienté objet (par exemple Java), je ne suis pas complètement au courant des subtilités de la discussion. Mais j'ai implémenté un singleton en PHP 4. Je l'ai fait comme un moyen de créer un gestionnaire de base de données «boîte noire» qui s'initialise automatiquement et qui n'a pas à passer des appels de fonction de haut en bas dans un cadre incomplet et quelque peu cassé.
Après avoir lu quelques liens de modèles singleton, je ne suis pas tout à fait sûr de pouvoir l'implémenter à nouveau de la même manière. Ce qui était vraiment nécessaire, c'était de multiples objets avec stockage partagé (par exemple, le handle de base de données réel) et c'est à peu près ce que mon appel s'est transformé.
Comme la plupart des modèles et algorithmes, utiliser un singleton «juste parce que c'est cool» est la mauvaise chose à faire. J'avais besoin d'un appel vraiment «boîte noire» qui ressemblait beaucoup à un singleton. Et l'OMI, c'est le moyen d'aborder la question: soyez conscient du modèle, mais regardez aussi sa portée plus large et à quel niveau son instance doit être unique.
la source
Que voulez-vous dire, quelles sont mes techniques pour l'éviter?
Pour «l'éviter», cela implique qu'il y a de nombreuses situations que je rencontre dans lesquelles le motif singleton est naturellement un bon ajustement, et donc que je dois prendre des mesures pour désamorcer ces situations.
Mais il n'y en a pas. Je n'ai pas à éviter le modèle singleton. Cela ne se produit tout simplement pas.
la source