Quelle différence réelle (c’est-à-dire pratique) existe-t-il entre une classe statique et un modèle singleton?
Les deux peuvent être appelés sans instanciation, les deux ne fournissent qu'une seule "instance" et aucun d'entre eux n'est thread-safe. Y a-t-il une autre différence?
Qu'est-ce qui vous fait dire qu'un singleton ou une méthode statique n'est pas thread-safe? Habituellement les deux devraient être implémentés pour être thread-safe.
La grande différence entre un singleton et un tas de méthodes statiques est que les singletons peuvent implémenter des interfaces (ou dériver de classes de base utiles, bien que ce soit moins courant, selon mon expérience), de sorte que vous pouvez faire passer le singleton comme s'il s'agissait "juste d'une autre " la mise en oeuvre.
La vraie réponse est par Jon Skeet, sur un autre forum ici .
Un singleton autorise l'accès à une seule instance créée - cette instance (ou plutôt une référence à cette instance) peut être transmise en tant que paramètre à d'autres méthodes et traitée comme un objet normal.
Une classe statique n'autorise que les méthodes statiques.
interface
avec une classe Singleton, mais les méthodes statiques d'une classe (ou, par exemple, un C # static class
) ne le peuvent pas.Le modèle Singleton présente plusieurs avantages par rapport aux classes statiques. Tout d'abord, un singleton peut étendre des classes et implémenter des interfaces, alors qu'une classe statique ne le peut pas (il peut étendre des classes, mais il n'hérite pas de ses membres d'instance). Un singleton peut être initialisé paresseusement ou de manière asynchrone, tandis qu'une classe statique est généralement initialisée lors de son premier chargement, ce qui peut entraîner des problèmes de chargeur de classes. Cependant, l'avantage le plus important est que les singletons peuvent être gérés de manière polymorphe sans obliger leurs utilisateurs à supposer qu'il n'y a qu'une seule instance.
Les classes static
ne sont pas pour tout ce qui a besoin d'état. Il est utile pour rassembler un ensemble de fonctions, à savoir Math
(ou Utils
dans des projets). Donc, le nom de la classe nous donne juste un indice où nous pouvons trouver les fonctions et rien de plus.
Singleton
est mon motif préféré et je l'utilise pour gérer quelque chose en un point unique. Il est plus souple que les classes static
et peut conserver son état. Il peut implémenter des interfaces, hériter d'autres classes et autoriser l'héritage.
Ma règle pour choisir entre static
et singleton
:
S'il y a un tas de fonctions qui devraient être gardées ensemble, alors static
est le choix. Tout ce qui nécessite un accès unique à certaines ressources peut être implémenté en tant que singleton
.
Classe statique: -
Vous ne pouvez pas créer l'instance de classe statique.
Chargé automatiquement par le CLR (Common Language Runtime) .NET Framework lorsque le programme ou l'espace de noms contenant la classe est chargé.
La classe statique ne peut pas avoir de constructeur.
Nous ne pouvons pas passer la classe statique à la méthode.
Nous ne pouvons pas hériter d'une classe statique dans une autre classe statique en C #.
Une classe ayant toutes les méthodes statiques.
Meilleures performances (les méthodes statiques sont liées au moment de la compilation)
Singleton: -
Vous pouvez créer une instance de l'objet et la réutiliser.
L'instance Singleton est créée pour la première fois à la demande de l'utilisateur.
La classe Singleton peut avoir un constructeur.
Vous pouvez créer l'objet de la classe singleton et le transmettre à la méthode.
La classe Singleton ne dit aucune restriction de l'héritage.
Nous pouvons disposer des objets d'une classe singleton mais pas d'une classe statique.
Les méthodes peuvent être remplacées.
Peut être chargé paresseux en cas de besoin (les classes statiques sont toujours chargées).
Nous pouvons implémenter une interface (la classe statique ne peut pas implémenter une interface).
Une classe statique est une classe qui ne comporte que des méthodes statiques, pour lesquelles un meilleur mot serait "fonctions". Le style de conception incarné dans une classe statique est purement procédural.
Singleton, en revanche, est un motif spécifique à OO design. Il s'agit d'une instance d'objet (avec toutes les possibilités inhérentes, telles que le polymorphisme), avec une procédure de création qui garantit qu'il n'y a qu'une seule instance de ce rôle particulier pendant toute sa durée de vie.
Dans le modèle singleton, vous pouvez créer le singleton en tant qu'instance d'un type dérivé. Vous ne pouvez pas le faire avec une classe statique.
Exemple rapide:
if( useD3D )
IRenderer::instance = new D3DRenderer
else
IRenderer::instance = new OpenGLRenderer
Pour développer Réponse de Jon Skeet
La grande différence entre un singleton et un tas de méthodes statiques réside dans le fait que les singletons peuvent implémenter des interfaces (ou dériver de classes de base utiles, bien que ce soit un IME moins courant), de sorte que vous puissiez faire circuler le singleton comme s'il s'agissait d'une implémentation "juste une autre".
Il est plus facile de travailler avec des singletons lorsque l’unité teste une classe. Partout où vous transmettez des singletons en tant que paramètre (constructeurs, setters ou méthodes), vous pouvez remplacer une version du singleton simulée ou tronquée.
Un autre avantage d'un singleton est qu'il peut facilement être sérialisé, ce qui peut s'avérer nécessaire si vous devez enregistrer son état sur un disque ou l'envoyer quelque part à distance.
Voici un bon article: http://javarevisited.blogspot.com.au/2013/03/difference-between-singleton-pattern-vs-static-class-Java.html
ne peut pas remplacer les méthodes, mais peut utiliser le masquage de méthode. ( Qu'est-ce que la méthode cache en Java? Même l'explication de JavaDoc est déroutante )
public class Animal {
public static void foo() {
System.out.println("Animal");
}
}
public class Cat extends Animal {
public static void foo() { // hides Animal.foo()
System.out.println("Cat");
}
}
En résumé, je n'utiliserais que des classes statiques pour conserver les méthodes util et utiliser Singleton pour tout le reste.
Modifications
les classes statiques sont également chargées paresseux. Merci @jmoreno ( Quand l'initialisation de classe statique a-t-elle lieu? )
masquage de méthode pour les classes statiques. Merci @ MaxPeng.
Je ne suis pas un grand théoricien OO, mais d'après ce que je sais, je pense que le polymorphisme est la seule caractéristique OO qui manque aux classes statiques par rapport à Singletons. Mais si vous n'en avez pas besoin, avec une classe statique, vous pouvez bien sûr avoir un héritage (pas sûr de l'implémentation d'interface) et une encapsulation de données et de fonctions.
Le commentaire de Morendil, "Le style de conception incarné dans une classe statique est purement procédural" Je me trompe peut-être, mais je ne suis pas d'accord. Dans les méthodes statiques, vous pouvez accéder aux membres statiques, ce qui serait exactement la même chose que les méthodes singleton accédant à leurs membres d'instance uniques.
modifier:
En fait, je pense maintenant qu’une autre différence est qu’une classe statique est instanciée au début du programme * et vit tout au long de sa vie, alors qu’un singleton est explicitement instancié à un point et peut être détruit aussi.
* ou il peut être instancié à la première utilisation, selon la langue, je pense.
Pour illustrer le propos de Jon, ce qui est montré ci-dessous ne peut pas être réalisé si Logger était une classe statique. La classe SomeClass
s'attend à ce qu'une instance de ILogger
implementation soit transmise à son constructeur.
La classe Singleton est importante pour que l'injection de dépendance soit possible.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var someClass = new SomeClass(Logger.GetLogger());
}
}
public class SomeClass
{
public SomeClass(ILogger MyLogger)
{
}
}
public class Logger : ILogger
{
private static Logger _logger;
private Logger() { }
public static Logger GetLogger()
{
if (_logger==null)
{
_logger = new Logger();
}
return _logger;
}
public void Log()
{
}
}
public interface ILogger
{
void Log();
}
}
Un singleton est simplement une classe normale qui IS est instanciée une seule fois et indirectement à partir du code client. La classe statique n'est pas instanciée. Pour autant que je sache, les méthodes statiques (la classe statique doit avoir des méthodes statiques) sont plus rapides que les méthodes non statiques.
Modifier:
Description de la règle de performance FxCop: "Les méthodes qui n’accèdent pas aux données d’instance ou les méthodes d’instance d’appel peuvent être marquées comme statiques (Partagé en VB). Après cela, le compilateur émettra des sites d’appel non virtuels à ces membres qui empêchera la vérification au moment de l'exécution de chaque appel garantissant que le pointeur d'objet actuel est non nul, ce qui peut entraîner un gain de performance mesurable pour le code sensible à la performance. Dans certains cas, l'impossibilité d'accéder à l'instance d'objet en cours représente un problème de correction. . "
Je ne sais pas si cela s'applique également aux méthodes statiques dans les classes statiques.
Les singleton sont instanciés, il n'y a qu'une seule instance jamais instanciée, d'où le single dans Singleton.
Une classe statique ne peut être instanciée que par elle-même.
Les principales différences sont les suivantes:
Je suis d'accord avec cette définition:
Le mot " unique " désigne un seul objet tout au long du cycle de vie de l'application. La portée est donc au niveau de l'application.
Le statique ne possède pas de pointeur d'objet. La portée est donc au niveau du domaine d'application.
De plus, les deux doivent être implémentés pour être thread-safe.
Vous pouvez trouver d’autres différences intéressantes à propos de: Singleton Pattern versus Static Class
Singleton est une meilleure approche du point de vue des tests. Contrairement aux classes statiques, singleton peut implémenter des interfaces et vous pouvez utiliser une instance fictive et les injecter.
Dans l'exemple ci-dessous, je vais illustrer ceci. Supposons que vous avez une méthode isGoodPrice () qui utilise une méthode getPrice () et que vous implémentez getPrice () en tant que méthode dans un singleton.
singleton qui fournit la fonctionnalité getPrice:
public class SupportedVersionSingelton {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
// calculate price logic here
return 0;
}
}
Utilisation de getPrice:
public class Advisor {
public boolean isGoodDeal(){
boolean isGoodDeal = false;
ICalculator supportedVersion = SupportedVersionSingelton.getInstance();
int price = supportedVersion.getPrice();
// logic to determine if price is a good deal.
if(price < 5){
isGoodDeal = true;
}
return isGoodDeal;
}
}
In case you would like to test the method isGoodPrice , with mocking the getPrice() method you could do it by:
Make your singleton implement an interface and inject it.
public interface ICalculator {
int getPrice();
}
Mise en œuvre finale Singleton:
public class SupportedVersionSingelton implements ICalculator {
private static ICalculator instance = null;
private SupportedVersionSingelton(){
}
public static ICalculator getInstance(){
if(instance == null){
instance = new SupportedVersionSingelton();
}
return instance;
}
@Override
public int getPrice() {
return 0;
}
// for testing purpose
public static void setInstance(ICalculator mockObject){
if(instance != null ){
instance = mockObject;
}
classe de test:
public class TestCalculation {
class SupportedVersionDouble implements ICalculator{
@Override
public int getPrice() {
return 1;
}
}
@Before
public void setUp() throws Exception {
ICalculator supportedVersionDouble = new SupportedVersionDouble();
SupportedVersionSingelton.setInstance(supportedVersionDouble);
}
@Test
public void test() {
Advisor advidor = new Advisor();
boolean isGoodDeal = advidor.isGoodDeal();
Assert.assertEquals(isGoodDeal, true);
}
}
Si nous utilisions la méthode statique pour implémenter getPrice (), il était difficile de simuler getPrice (). Vous pouvez simuler l'électricité statique avec une maquette électrique, mais tous les produits ne peuvent pas l'utiliser.
Une différence notable est l’instanciation différée fournie avec les singletons.
Avec les classes statiques, il est créé par le CLR et nous n'avons aucun contrôle dessus. avec des singletons, l'objet est instancié à la première tentative d'accès.
Notre infrastructure de base de données établit des connexions avec le back-end. Pour éviter les lectures déplacées sur plusieurs utilisateurs, nous avons utilisé un modèle singleton pour nous assurer de disposer d'une instance unique à tout moment.
En c #, une classe statique ne peut pas implémenter une interface. Lorsqu'une classe d'instance unique doit implémenter une interface pour des contrats commerciaux ou des objectifs IoC, c'est ici que j'utilise le modèle Singleton sans classe statique.
Singleton offre un moyen de maintenir l'état dans des scénarios sans état
J'espère que ça vous aide ..
Dans de nombreux cas, ces deux n’ont aucune différence pratique, en particulier si l’instance singleton ne change jamais ou change très lentement, par exemple. maintien des configurations.
Je dirais que la plus grande différence est qu'un singleton est toujours un bean Java normal, contrairement à une classe spécialisée Java statique uniquement. Et pour cette raison, un singleton est accepté dans beaucoup plus de situations; c'est en fait la stratégie d'instanciation de Spring Framework par défaut. Le consommateur peut savoir ou ne pas savoir qu’il s’agit d’un singleton, il le traite simplement comme un bean normal Java. Si les exigences changent et si un singleton doit devenir un prototype, comme nous le voyons souvent au printemps, cela peut se faire de manière totalement transparente, sans modification de code pour le consommateur.
Quelqu'un d'autre a mentionné plus tôt qu'une classe statique devrait être purement procédurale, par exemple. Java.lang.Math. Dans mon esprit, une telle classe ne devrait jamais être transmise et ils ne devraient jamais considérer que des attributs statiques. Pour tout le reste, utilisez un singleton, car il est beaucoup plus flexible et facile à gérer.
J'ai lu ce qui suit et pense que c'est logique aussi:
S'occuper des affaires
N'oubliez pas que l'une des règles les plus importantes OO est qu'un objet est responsable de lui-même. Cela signifie que les questions relatives au cycle de vie d'une classe doivent être traitées dans la classe, et non déléguées à des constructions de langage telles que static, etc.
extrait du livre Processus de la Pensée Orientée, 4e éd.
Dans un article que j'ai écrit, j'ai décrit mon point de vue sur les raisons pour lesquelles le singleton est bien meilleur qu'une classe statique:
Nous pouvons créer l'objet de singleton class et le passer à method.
La classe Singleton n'impose aucune restriction d'héritage.
Nous ne pouvons pas disposer les objets d'une classe statique mais pouvons singleton une classe.
une. Sérialisation - Les membres statiques appartiennent à la classe et ne peuvent donc pas être sérialisés.
b. Bien que nous ayons rendu le constructeur privé, les variables membres statiques seront toujours portées à la sous-classe.
c. Nous ne pouvons pas procéder à une initialisation lente car tout sera chargé lors du chargement de la classe uniquement.
Du point de vue du client, le comportement statique du client est connu, mais le comportement de Singleton peut être masqué du client. Le client peut ne jamais savoir qu’il n’y a qu’une seule instance avec laquelle il joue encore et encore.
Il existe une énorme différence entre une instance seule classe statique (c'est-à-dire une instance unique d'une classe, qui se trouve être une variable statique ou globale) et un pointeur statique unique = à une instance de la classe sur le tas:
Lorsque votre application se ferme, le destructeur de l'instance de classe statique sera appelé. Cela signifie que si vous utilisiez cette instance statique en tant que singleton, votre singleton cesserait de fonctionner correctement. S'il y a toujours du code en cours d'utilisation qui utilise ce singleton, par exemple dans un autre thread, ce code risque de planter.
Un classe statique dans Java n'a que des méthodes statiques. C'est un conteneur de fonctions. Il est créé sur la base d'une conception de programmation procédurale.
Singleton class est un motif en conception orientée objet. Une classe Singleton n'a qu'une seule instance d'un objet dans la machine virtuelle Java. Ce modèle est implémenté de telle sorte qu'il n'y ait toujours qu'une seule instance de cette classe dans la JVM.
Quand je veux un cours avec toutes les fonctionnalités, par exemple il y a beaucoup de méthodes et de variables, j'utilise singleton;
Si je veux une classe avec seulement une ou deux méthodes, par ex. Classe MailService, qui n'a qu'une seule méthode SendMail () J'utilise une classe et une méthode statiques.
La différence dans ma tête réside dans la mise en œuvre de la programmation orientée objet (Singleton/Prototype) ou de la programmation fonctionnelle (statique).
Nous sommes trop concentrés sur le nombre d'objets créés par un motif singleton alors que nous devrions nous concentrer sur le fait qu'à la fin, nous tenons un objet. Comme d'autres l'ont déjà dit, il peut être étendu, passé en paramètre mais surtout, il est complet.
D'autre part, statique est utilisé pour implémenter la programmation fonctionnelle. Les membres statiques appartiennent à une classe. Ils sont apatrides.
A propos saviez-vous que vous pouvez créer des classes statiques singleton :)
Si je comprends bien la différence entre une classe Static et une classe Singleton non statique, le type statique est simplement un "type" non instancié en C #, où Singleton est un véritable "objet". En d'autres termes, tous les membres statiques d'une classe statique sont affectés au type, mais dans le Singleton, ils sont logés sous l'objet. Mais gardez à l'esprit qu'une classe statique se comporte toujours comme un type de référence, mais pas comme un type de valeur comme un Struct.
Cela signifie que lorsque vous créez un Singleton, parce que la classe elle-même n'est pas statique mais que son membre l'est, l'avantage est que le membre statique à l'intérieur du Singleton qui se réfère à lui-même est connecté à un "objet" réel plutôt qu'à un "type" creux de lui-même. Cela clarifie maintenant la différence entre un singleton statique et non statique, au-delà de ses autres fonctionnalités et de son utilisation de la mémoire, ce qui est déroutant pour moi.
Les deux utilisent des membres statiques qui sont des copies uniques d'un membre, mais Singleton encapsule le membre référencé autour d'un véritable "objet" instancié dont l'adresse existe en plus de son membre statique. Cet objet lui-même a des propriétés dans lesquelles in peut être passé et référencé, ajoutant de la valeur. La classe Static est juste un type, elle n'existe donc pas, sauf pour pointer sur ses membres statiques. Ce concept a en quelque sorte cimenté l'objectif de la classe Singleton vs Static au-delà de l'héritage et d'autres questions.
Exemple avec une classe statique
public class Any {
private static Any instance = new Any();
private Singleton() {
System.out.println("creating");
}
}
avec des motifs singleton n'existent qu'une instance:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
System.out.println("creating");
if (instance != null) {
throw new RuntimeException("Imposible create a new instance ");
}
}
}