Quand devez-vous utiliser le pattern singleton au lieu d'une classe statique?[fermé]

StackOverflow https://stackoverflow.com/questions/46541

  •  09-06-2019
  •  | 
  •  

Question

Nom de l'considérations de conception pour choisir entre l'utilisation d'un singleton par rapport à une classe statique.En faisant cela, vous êtes en quelque sorte contraint de mettre en contraste les deux, donc quel que soit le contraste vous pouvez venir avec sont également utiles dans la démonstration de votre processus de pensée!Aussi, chaque enquêteur aime voir des exemples illustratifs.:)

Était-ce utile?

La solution

  • Les Singletons peuvent implémenter des interfaces et hériter d'autres classes.
  • Les Singletons peuvent être facilement chargées.Seulement quand il est nécessaire.C'est très pratique si l'initialisation comprend ressource coûteuse de chargement ou de connexions de base de données.
  • Les Singletons offrir un objet réel.
  • Les Singletons peut être étendue dans une usine.L'objet de gestion de derrière les scènes, c'est abstrait, il est donc préférable maintenable et les résultats dans un code de meilleure qualité.

Autres conseils

Comment "éviter à la fois"?Les Singletons et les classes statiques:

  • Peuvent introduire de l'état global
  • Obtenir étroitement associée à plusieurs autres classes
  • Masquer les dépendances
  • Peut faire des tests unitaires de classes dans l'isolement difficile

Au lieu de cela, regarder dans L'Injection De Dépendance et L'Inversion de Contrôle Conteneur des bibliothèques.Plusieurs de le Cio bibliothèques poignée de gestion de durée de vie pour vous.

(Comme toujours, il y a des exceptions, telle que les classes de mathématiques et de C# les méthodes d'extension.)

Je dirais la seule différence est la syntaxe:MySingleton.Actuel.Quel que soit() vs MySingleton.Quel que soit().L'état, comme David mentionné, est en fin de compte "statique" dans les deux cas.


EDIT:Bury brigade est venu de digg ...de toute façon, j'ai pensé à une affaire qui aurait besoin d'un singleton.Les classes statiques ne peuvent pas hériter d'une classe de base, ni de mettre en œuvre une interface (au moins dans .Net ils ne peuvent pas).Donc, si vous avez besoin de cette fonctionnalité, vous devez utiliser un singleton.

L'un de mes préférés des discussions sur ce problème ici (site d'origine vers le bas, maintenant lié à l' Internet Archive Wayback Machine.)

Pour résumer les avantages de la flexibilité d'un Singleton:

  • un Singleton peut être facilement converti dans une usine
  • un Singleton peut être facilement modifié pour renvoyer différentes les sous-classes
  • il peut en résulter une plus maintenable application

Une classe statique avec une charge de variables statiques est un peu un hack.

/**
 * Grotty static semaphore
 **/
 public static class Ugly {

   private static int count;

   public synchronized static void increment(){
        count++;
   }

   public synchronized static void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized static boolean isClear(){
         return count==0;    

    }
   }

Un singleton, avec un exemple, c'est mieux.

/**
 * Grotty static semaphore
 **/
 public static class LessUgly {
   private static LessUgly instance;

   private int count;

   private LessUgly(){
   }

   public static synchronized getInstance(){
     if( instance==null){
        instance = new LessUgly();
     }
     return instance;
   }
   public synchronized void increment(){
        count++;
   }

   public synchronized void decrement(){
        count--;
        if( count<0 ) {
            count=0;
        }
   }

   public synchronized boolean isClear(){
         return count==0;    

    }
   }

L'état est dans l'instance.

Si le singleton peut être modifié plus tard pour faire de mise en commun, le fil-les instances locales, etc.Et aucun des déjà écrit, le code doit changer pour obtenir le bénéfice.

public static class LessUgly {
       private static Hashtable<String,LessUgly> session;
       private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
       private static final POOL_SIZE=5;
       private int count;

       private LessUgly(){
       }

       public static synchronized getInstance(){
         if( session==null){
            session = new Hashtable<String,LessUgly>(POOL_SIZE);
            for( int i=0; i < POOL_SIZE; i++){
               LessUgly instance = new LessUgly();  
               freePool.add( instance)
            }
         }
         LessUgly instance = session.get( Session.getSessionID());
         if( instance == null){
            instance = freePool.read();
         }
         if( instance==null){
             // TODO search sessions for expired ones. Return spares to the freePool. 
             //FIXME took too long to write example in blog editor.
         }
         return instance;
       }     

Il est possible de faire quelque chose de similaire avec une classe statique, mais il y aura par appel les frais généraux indirects de l'expédition.

Vous pouvez obtenir de l'instance et de le transmettre à une fonction comme argument.Ce code permet d'être dirigé vers le "droit" de singleton.Nous savons que vous aurez seulement besoin de l'un de...jusqu'à ce que vous n'avez pas.

Le gros avantage est que la dynamique des singletons peuvent être thread safe, alors qu'une classe statique ne peut pas, sauf si vous modifiez un caractère secret singleton.

Pensez à un singleton comme un service.C'est un objet qui fournit un ensemble spécifique de fonctionnalité.E. g.

ObjectFactory.getInstance().makeObject();

La fabrique d'objet est un objet qui effectue un service spécifique.

En revanche, une classe de méthodes statiques est un ensemble d'actions que vous pouvez effectuer, organisée dans un groupe (La classe).E. g.

StringUtils.reverseString("Hello");
StringUtils.concat("Hello", "World");

Le StringUtils exemple ici est un ensemble de fonctionnalités qui peuvent être appliquées partout.Le singleton, factory objet est un type spécifique de l'objet avec une responsabilité claire, qui peut être créé et adopté dans les cas nécessaires.

Les classes statiques sont instanciés lors de l'exécution.Cela pourrait être une perte de temps.Les Singletons peuvent être instanciés uniquement lorsque cela est nécessaire.

Les Singletons ne doit pas être utilisé de la même manière que les classes statiques.Dans essense,

MyStaticClass.GetInstance().DoSomething();

est essentiellement la même que

MyStaticClass.DoSomething();

Ce que vous devez réellement faire est de le traitement de l'singleton comme juste un autre objet.Si un service a besoin d'une instance du singleton de type, puis passer que l'instance dans le constructeur:

var svc = new MyComplexServce(MyStaticClass.GetInstance());

Le service ne devrait pas être conscient que l'objet est un singleton, et devrait traiter l'objet comme un objet.

L'objet peut certainement être mises en œuvre, comme un détail d'implémentation et comme un aspect de l'ensemble de la configuration, comme un singleton si cela rend les choses plus faciles.Mais les choses que l'utilisation de l'objet ne doit pas avoir pour savoir si l'objet est un singleton ou pas.

Si par "classe statique" vous voulez dire une classe qui n'a que des variables statiques, puis ils peut effectivement maintenir l'état.Ma compréhension est que la seule différence serait que vous accédez à cette chose.Par exemple:

MySingleton().getInstance().doSomething();

rapport

MySingleton.doSomething();

Le fonctionnement interne de MySingleton sera évidemment différent entre eux, mais, enfilez les questions de sécurité de côté, ils permettront à la fois d'effectuer la même en ce qui concerne le code du client.

Le pattern Singleton est généralement utilisé pour le service de l'instance indépendante données statiques ou lorsque plusieurs threads peuvent accéder aux données en même temps.Un exemple peut être des codes d'état.

Les Singletons ne doit jamais être utilisé (sauf si vous considérez une classe sans mutable état d'un singleton)."les classes statiques" ne devrait avoir aucun mutable état, autres que peut-être thread-safe caches et la comme.

Pratiquement n'importe quel exemple d'un singleton montre comment ne pas le faire.

Si un singleton est quelque chose que vous pouvez vous débarrasser, nettoyer après cela, vous pouvez considérer quand c'est une ressource limitée (ie.1) que vous n'avez pas besoin tout le temps, et d'avoir une forme de mémoire ou le coût de la ressource quand il est alloué.

Le code de nettoyage paraît plus naturel quand vous avez un singleton, par opposition à une classe statique contenant de l'état statique des champs.

Toutefois, le code ressemblera un peu le même de toute façon, donc si vous avez plus de raisons spécifiques pour le demander, peut-être vous devriez élaborer.

Les deux peuvent être assez semblables, mais n'oubliez pas que le vrai Singleton doit lui-même être instancié (accordée, une fois) et ont ensuite servi.En PHP, base de données de la classe qui retourne une instance de mysqli n'est pas vraiment un Singleton (comme certains l'appellent), parce que c'est de retourner une instance d'une autre classe, une instance de la classe qui dispose de l'instance en tant que membre statique.

Donc, si vous êtes en train de rédiger une nouvelle classe que vous prévoyez de n'autoriser qu'une seule instance de dans votre code, vous pourriez aussi bien de l'écrire comme un Singleton.Il pense que l'écriture d'un plain jane classe et en ajoutant à faciliter la seule instanciation d'exigence.Si vous êtes à l'aide de quelqu'un d'autre classe que vous ne pouvez pas modifier (comme mysqli), vous devez être en utilisant une classe statique (même si vous ne le préfixe de sa définition avec le mot-clé).

Les Singletons sont plus souples, ce qui peut être utile dans le cas où vous souhaitez que la méthode d'Instance pour revenir concrètes différentes sous-classes de la Singleton de type basé sur un certain contexte.

Les classes statiques ne peuvent pas être passés comme arguments;les instances d'un singleton peut être.Comme mentionné dans d'autres réponses, montre pour les problèmes de threading avec les classes statiques.

rp

Un singleton peut avoir un constructeur et un destructeur.En fonction de votre langue, le constructeur peut être appelé automatiquement la première fois que votre singleton est utilisé, ou jamais si votre singleton n'est pas utilisé du tout.Une classe statique aurait pas une telle initialisation automatique.

Une fois une référence à un objet singleton est obtenu, il peut être utilisé comme tout autre objet.Le code client peut même pas besoin de connaître son à l'aide d'un singleton si une référence pour le singleton est stocké précédemment sur:

Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

De toute évidence, cela rend les choses plus faciles, lorsque vous choisissez d'abandonner le pattern Singleton en faveur d'un motif réel, comme le Cio.

Utiliser le pattern singleton lorsque vous avez besoin de calculer quelque chose à l'exécution qui vous permettrait de calculer au moment de la compilation, si vous pouviez, comme les tables de recherche.

Je pense à un endroit où Singleton aura plus de sens que la statique de la classe, c'est quand vous avez à construire un bassin de ressources coûteuses (comme des connexions de base de données).Vous ne seriez pas intéressé par la création de la piscine si jamais personne ne les utilise (statique de la classe signifie que vous ne le coûteux travail lorsque la classe est chargée).

Un singleton est aussi une bonne idée si vous voulez forcer l'efficacité de la mise en cache de données.par exemple, j'ai une classe qui ressemble à des définitions dans un document xml.Depuis l'analyse du document peut prendre un certain temps, j'ai mis en place un cache de définitions (j'utilise SoftReferences pour éviter outOfmemeoryErrors).Si l'définition n'est pas dans le cache, je ne le coûteux d'analyse xml.Sinon je retourner une copie à partir du cache.Puisque le fait d'avoir plusieurs caches signifierait j'ai encore pourrait avoir à charger la même définition à plusieurs reprises, j'ai besoin d'avoir une statique de cache.Je choisis de mettre en œuvre cette classe comme un singleton pour que je puisse écrire la classe à l'aide seulement de la normale (non statique) de données des membres.Cela me permet de créer un istantiation de la classe si j'en ai besoin pour une raison quelconque (sérialisation, tests unitaires, etc.)

Singleton, c'est comme un service, comme déjà mentionné.Pro, c'est sa flexibilité.Statique, eh bien, vous avez besoin de quelques parties statiques afin de mettre en œuvre Singleton.

Singleton a code pour prendre soin de l'instanciation de th réelle de l'objet, qui peut être d'une grande aide si vous exécutez dans la course des problèmes.Dans une solution statique vous pouvez avoir besoin pour faire face à des courses de problèmes à codes multiples endroits.

Cependant, même en tant que Singleton peut être construit avec certaines variables statiques, vous pouvez être en mesure de le comparer avec 'goto'.Il peut toute utiles pour la construction d'autres structures, mais vous avez vraiment besoin de savoir comment l'utiliser et ne devraient pas "surutilisation" il.Par conséquent, la recommandation générale est de s'en tenir à un Singleton, et l'utilisation statique si vous devez.

vérifiez également l'autre post: Pourquoi choisir une classe statique sur un singleton mise en œuvre?

reportez-vous cette

résumé:

un.Une simple règle de base que vous pouvez suivre est si elle n'a pas besoin de maintenir un état, vous pouvez utiliser une classe Statique, sinon vous devez utiliser un Singleton.

b.l'utilisation d'un Singleton est si elle est particulièrement “lourds” de l'objet.Si votre objet est volumineux et prend une quantité raisonnable de mémoire, beaucoup de n/w appels(pool de connexions) ..etc.Assurez-vous que sa ne va pas être instancié plusieurs fois.Une classe Singleton aidera à prévenir de tels cas jamais

Lorsque la classe unique des besoins de l'état.Les Singletons de maintenir un état global, les classes statiques ne le font pas.

Par exemple, faire un helper autour d'une classe de registre:Si vous avez changable de la ruche (HKey Current User vsHKEY Local Machine), vous pourriez aller:

RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine

Maintenant, tous les appels supplémentaires à qui singleton va fonctionner sur la Machine Locale de la ruche.Sinon, à l'aide d'une classe statique, vous devez spécifier que les Locaux de Machines de la ruche everytiem, ou avoir une méthode comme ReadSubkeyFromLocalMachine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top