design-patterns - stadt - singleton uml




Wann sollten Sie das Singleton-Muster anstelle einer statischen Klasse verwenden? (15)

Die beiden können sehr ähnlich sein, aber denken Sie daran, dass der wahre Singleton selbst instanziiert (einmal vergeben) und dann bedient werden muss. Eine PHP-Datenbankklasse, die eine Instanz von mysqli ist nicht wirklich ein Singleton (wie manche Leute es nennen), weil sie eine Instanz einer anderen Klasse zurückgibt, keine Instanz der Klasse, die die Instanz als statisches Mitglied hat.

Wenn Sie also eine neue Klasse schreiben, der Sie nur eine Instanz in Ihrem Code erlauben möchten, können Sie sie auch als Singleton schreiben. Stellen Sie sich das so vor, als würden Sie eine Klasse für "jane-jane" schreiben und sie hinzufügen, um die Anforderungen für die Einzelinstanziierung zu vereinfachen. Wenn Sie die Klasse einer anderen Person verwenden, die Sie nicht ändern können (wie mysqli ), sollten Sie eine statische Klasse verwenden (auch wenn Sie ihrer Definition nicht das Schlüsselwort voranstellen).

Benennen Sie die Entwurfsüberlegungen bei der Entscheidung zwischen der Verwendung eines singleton und einer statischen Klasse. Wenn du dies tust, bist du gezwungen, die beiden zu kontrastieren, also sind alle Kontraste, die du dir vorstellen kannst, auch nützlich, um deinen Denkprozess zu zeigen! Außerdem mag jeder Interviewer gerne illustrative Beispiele. :)


Ein Singleton ist auch eine gute Idee, wenn Sie ein effizientes Caching von Daten erzwingen möchten. Zum Beispiel habe ich eine Klasse, die Definitionen in einem XML-Dokument nachschlägt. Da das Parsing des Dokuments einige Zeit dauern kann, habe ich einen Cache mit Definitionen eingerichtet (ich verwende SoftReferences, um outOfmemoryErrors zu vermeiden). Wenn die gewünschte Definition nicht im Cache ist, mache ich das teure XML-Parsing. Ansonsten gebe ich eine Kopie aus dem Cache zurück. Da mehrere Caches haben würde ich immer noch die gleiche Definition mehrere Male laden müssen, muss ich einen statischen Cache haben. Ich entschied mich, diese Klasse als Singleton zu implementieren, so dass ich die Klasse nur mit normalen (nicht statischen) Datenmembern schreiben konnte. Dadurch kann ich immer noch eine Beschreibung der Klasse erstellen, wenn ich sie aus irgendeinem Grund brauche (Serialisierung, Komponententest usw.)


Eine meiner Lieblingsdiskussionen über dieses Problem ist here (ursprüngliche Seite unten, jetzt verbunden mit Internet Archive Wayback Machine .)

Um die Flexibilitätsvorteile eines Singleton zusammenzufassen:

  • Ein Singleton kann leicht in eine Fabrik umgewandelt werden
  • Ein Singleton kann leicht modifiziert werden, um verschiedene Unterklassen zurückzugeben
  • Dies kann zu einer wartungsfreundlicheren Anwendung führen

Eine statische Klasse mit einer Ladung statischer Variablen ist ein bisschen wie ein 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;    

    }
   }

Ein Singleton mit einer tatsächlichen Instanz ist besser.

/**
 * 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;    

    }
   }

Der Staat ist NUR in der Instanz.

So kann das Singleton später geändert werden, um Pooling, thread-lokale Instanzen usw. zu machen. Und keiner der bereits geschriebenen Codes muss geändert werden, um den Vorteil zu erhalten.

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;
       }     

Es ist möglich, etwas Ähnliches mit einer statischen Klasse zu tun, aber es wird einen pro-Aufruf-Overhead im indirekten Versand geben.

Sie können die Instanz abrufen und als Argument an eine Funktion übergeben. Dadurch kann der Code zum "richtigen" Singleton geleitet werden. Wir wissen, dass du nur eins brauchst ... bis du es nicht tust.

Der große Vorteil ist, dass Stateful Singletons threadsicher gemacht werden können, während eine statische Klasse das nicht kann, es sei denn man modifiziert sie zu einem geheimen Singleton.


Ich würde argumentieren, der einzige Unterschied ist die Syntax: MySingleton.Current.Whatever () vs MySingleton.Whatever (). Der Staat ist, wie David erwähnte, in beiden Fällen letztlich "statisch".

EDIT: Die Bury Brigade kam von digg ... jedenfalls dachte ich an einen Fall, der ein Singleton erfordern würde. Statische Klassen können weder von einer Basisklasse erben noch eine Schnittstelle implementieren (zumindest in .Net können sie nicht). Wenn Sie diese Funktionalität benötigen, müssen Sie ein Singleton verwenden.


Singleton ist wie ein Service, wie bereits erwähnt. Pro ist seine Flexibilität. Statisch, nun, Sie brauchen einige statische Teile, um Singleton zu implementieren.

Singleton hat einen Code, der für die Instanziierung des eigentlichen Objekts sorgt, was eine große Hilfe sein kann, wenn Sie Rennprobleme bekommen. In einer statischen Lösung müssen Sie möglicherweise mit Rennproblemen an mehreren Codestellen umgehen.

Wie auch Singleton mit einigen statischen Variablen konstruiert werden kann, können Sie es mit "goto" vergleichen. Es kann sehr nützlich sein, um andere Strukturen zu bauen, aber Sie müssen wirklich wissen, wie man es benutzt und es nicht "überbeanspruchen" sollte. Daher empfiehlt es sich, bei Singleton zu bleiben und bei Bedarf auch statisch zu bleiben.

Überprüfen Sie auch den anderen Beitrag: Warum wählen Sie eine statische Klasse über eine Singleton-Implementierung?


Singletons sind flexibler, was in Fällen nützlich sein kann, in denen die Instanzmethode verschiedene konkrete Unterklassen des Singletontyps basierend auf einem bestimmten Kontext zurückgeben soll.


Singletons sollten nicht wie statische Klassen verwendet werden. Im Grunde genommen,

MyStaticClass.GetInstance().DoSomething();

ist im Wesentlichen das Gleiche wie

MyStaticClass.DoSomething();

Was Sie eigentlich tun sollten, ist , das Singleton als ein anderes Objekt zu behandeln . Wenn ein Service eine Instanz des Singletontyps benötigt, übergeben Sie diese Instanz im Konstruktor:

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

Der Dienst sollte sich nicht bewusst sein, dass das Objekt ein Singleton ist, und sollte das Objekt nur als ein Objekt behandeln.

Das Objekt kann sicherlich als ein Implementierungsdetail und als ein Aspekt der Gesamtkonfiguration als ein Singleton implementiert werden, wenn dies die Dinge einfacher macht. Aber die Dinge, die das Objekt benutzen, sollten nicht wissen müssen, ob das Objekt ein Singleton ist oder nicht.


Statische Klassen können nicht als Argumente übergeben werden; Instanzen eines Singleton können sein. Wie in anderen Antworten erwähnt, achten Sie auf Threading-Probleme mit statischen Klassen.

rp


Statische Klassen werden zur Laufzeit instanziiert. Dies könnte zeitaufwendig sein. Singletons können nur bei Bedarf instanziiert werden.


Verweise codeofdoom.com/wordpress/2008/04/20/…

Zusammenfassung:

ein. Eine einfache Faustregel, der Sie folgen können, ist, wenn Sie den Zustand nicht beibehalten müssen, können Sie eine statische Klasse verwenden, andernfalls sollten Sie ein Singleton verwenden.

b. Verwenden Sie ein Singleton, wenn es sich um ein besonders "schweres" Objekt handelt. Wenn Ihr Objekt groß ist und eine angemessene Menge an Arbeitsspeicher belegt, viele N / W-Aufrufe (Verbindungspool) ..etc. Um sicherzustellen, dass es nicht mehrfach instanziiert wird. Eine Singleton-Klasse wird dazu beitragen, einen solchen Fall zu verhindern


Verwenden Sie das Singleton-Muster, wenn Sie zur Laufzeit etwas berechnen müssen, das Sie bei der Kompilierung berechnen könnten, wie beispielsweise Nachschlagetabellen.


Wenn die einzelne Klasse Status benötigt. Singletons erhalten einen globalen Zustand, statische Klassen nicht.

Zum Beispiel, einen Helper um eine Registrierungsklasse herum zu machen: Wenn Sie eine änderbare Struktur haben (HKey Current User vs. HKEY Local Machine), könnten Sie gehen:

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

Jetzt werden alle weiteren Aufrufe dieses Singletons in der lokalen Maschinenstruktur ausgeführt. Andernfalls müssten Sie bei Verwendung einer statischen Klasse angeben, dass die Datei "Local Machine" auf jeder Ebene liegt, oder über eine Methode wie " ReadSubkeyFromLocalMachine .


Wenn ein Singleton etwas ist, über das man verfügen kann, um danach aufzuräumen, kann man es in Betracht ziehen, wenn es eine begrenzte Ressource (dh nur eine davon) ist, die man nicht ständig braucht und irgendeine Art von Speicher oder Ressourcenkosten, wenn sie zugewiesen werden.

Der Bereinigungscode sieht natürlicher aus, wenn Sie einen Singleton haben, im Gegensatz zu einer statischen Klasse, die statische Statusfelder enthält.

Der Code wird jedoch in beiden Fällen gleich aussehen. Wenn Sie also genauere Gründe für Ihre Fragen haben, sollten Sie das vielleicht näher ausführen.


  • Singletons können Schnittstellen implementieren und von anderen Klassen erben.
  • Singletons können faul geladen werden. Nur wenn es wirklich benötigt wird. Das ist sehr praktisch, wenn die Initialisierung teure Ressourcenladungen oder Datenbankverbindungen beinhaltet.
  • Singletons bieten ein echtes Objekt.
  • Singletons können zu einer Fabrik erweitert werden. Das Objektmanagement hinter den Kulissen ist abstrakt, so dass es besser wartbar ist und zu besserem Code führt.




design-patterns