J'ai vu certaines personnes dans SO commenter que le modèle Singleton est un anti-modèle. Je voudrais savoir pourquoi ?
Réponses
Trop de publicités?Essais
L'une des raisons est que les singletons ne sont pas faciles à gérer avec les tests unitaires. Vous ne pouvez pas contrôler l'instanciation et, de par leur nature même, ils peuvent conserver un état à travers les invocations.
C'est pourquoi le principe de l'injection de dépendance est populaire. Chaque classe est injectée (configurée) avec les classes dont elle a besoin pour fonctionner (plutôt que de dériver via des accesseurs singleton) et les tests peuvent donc contrôler les instances de classe dépendantes à utiliser (et fournir des mocks si nécessaire).
Les frameworks tels que Spring contrôlent le cycle de vie de leurs objets et créent souvent des singletons, mais ces objets sont injectés dans leurs objets dépendants par le framework. Ainsi, la base de code elle-même ne traite pas les objets comme des singletons.
par exemple, plutôt que ceci (par exemple)
public class Portfolio {
private Calculator calc = Calculator.getCalculator();
}
vous injecteriez la calculatrice :
public class Portfolio {
public Portfolio(Calculator c) {
this.calc = c;
}
}
Ainsi, le Portfolio
ne sait pas combien d'instances de l'objet Calculator
existent. Les tests peuvent injecter un Calculator
qui facilitent les tests.
Concurrence
En se limitant à une seule instance d'un objet, les options de threading sont limitées. L'accès à l'objet singleton peut devoir être protégé (par exemple par synchronisation). Si vous pouvez maintenir plusieurs instances de ces objets, vous pouvez alors adapter le nombre d'instances aux threads en cours d'exécution et augmenter les capacités concurrentes de votre base de code.
Mon opinion personnelle est qu'il s'agit d'une violation du principe de responsabilité unique. Les objets singleton sont responsables à la fois de leur objectif et du contrôle du nombre d'instances qu'ils produisent, ce qui, à mon avis, n'est pas correct.
C'est pourquoi de nombreuses personnes délèguent le contrôle à un objet d'usine.
[Mutable] Le singleton est un anti-modèle d'un anti-modèle.
L'état global (ou état ambiant) est l'anti-modèle sous-jacent le plus important. Avec l'état global, vous avez un grand blog de dépendance à travers votre programme. Cela affecte les tests, mais ce n'est qu'une partie des conséquences d'une mauvaise programmation.
De plus, Singleton ajoute un niveau de complexité complètement inutile par rapport à une simple déclaration de mutabilité static
champs.
Les singletons en tant que tels ne sont pas nécessairement un anti-modèle, mais ils n'ont que peu d'avantages et deviennent un anti-modèle lorsqu'ils sont mal utilisés (ce qui arrive souvent).
Souvent, les singletons ne sont pas du tout des singletons, mais des "variables globales déguisées". En outre, ils sont souvent utilisés lorsque la propriété "une seule instance" n'est pas un avantage. (ce qui est contrebalancé par le fait que la mise en œuvre est souvent erronée).
En outre, ils peuvent être difficiles à mettre en œuvre en tenant compte du multithreading (souvent mal fait ou inefficace), et ils perdent la plupart de leurs avantages si l'on veut contrôler leur instanciation.
Si vous voulez contrôler l'instanciation, vous devez le faire à la main à un moment donné du programme, mais vous pouvez tout aussi bien créer une instance d'un objet normal et la transmettre.
Si l'ordre de destruction vous préoccupe, vous devez également le mettre en œuvre manuellement. Un seul objet automatique dans la fonction principale est tellement plus propre et plus facile.
Vous pouvez avoir de nombreuses exigences à l'égard du singleton :
- Initialisation paresseuse ;
- élimination appropriée ;
- (un par fil, par exemple).
Généralement, vous aurez aussi un grand nombre de singletons dans votre application, et l'option Singleton ne permet pas de réutiliser le code. Ainsi, si vous voulez implémenter toutes ces préoccupations pour tous vos singletons, vous verrez immédiatement sa anti-modèle qualité.