Frage

Der Singleton-Muster ist ein voll eingezahltes Mitglied der GoF'S Musterbuch, aber in letzter Zeit scheint es von der Entwicklerwelt eher verwaist zu sein.Ich verwende immer noch ziemlich viele Singletons, insbesondere für Fabrikklassen, und obwohl man bei Multithreading-Problemen (wie eigentlich bei jeder Klasse) etwas vorsichtig sein muss, verstehe ich nicht, warum sie so schrecklich sind.

Insbesondere Stack Overflow scheint davon auszugehen, dass sich alle einig sind, dass Singletons böse sind.Warum?

Bitte untermauern Sie Ihre Antworten mit „Fakten, Referenzen oder spezifisches Fachwissen"

War es hilfreich?

Lösung

paraphrasiert von Brian Button:

  1. Sie werden im Allgemeinen als globale Instanz verwendet wird, warum ist das so schlimm? Weil Sie die Abhängigkeiten Ihrer Anwendung in Ihrem Code verstecken, anstatt sie über die Schnittstellen auszusetzen. Macht etwas global, es zu vermeiden um ein Codegeruch passiert.

  2. Sie verletzen die einzigen Verantwortung Prinzip : auf Grund der Tatsache, dass sie kontrollieren ihre eigene Schöpfung und Lebenszyklus.

  3. Sie von Natur aus Code verursachen fest gekoppelt sein. Das macht sie aus im Test ziemlich schwierig, in vielen Fällen vorgetäuscht.

  4. Sie tragen Zustand um für die Lebensdauer der Anwendung. Ein weiterer Hit der Prüfung, da Sie mit einer Situation kann am Ende, wo Tests bestellt werden müssen, die ein großes Nein für Unit-Tests ist. Warum? Da jede Einheit Test sollte vom anderen unabhängig sein.

Andere Tipps

Singletons lösen ein (und nur ein) Problem.

Ressourcenkonflikte.

Wenn Sie etwas Ressource, die

( 1 ) nur eine einzige Instanz hat, und

( 2 ) Sie, dass einzelne Instanz verwalten müssen,

Sie brauchen einen Singleton .

Es gibt nicht viele Beispiele. Eine Protokolldatei ist die große. Sie wollen nicht nur eine einzelne Protokolldatei verlassen. Sie möchten spülen, synchronisieren und es richtig zu schließen. Dies ist ein Beispiel für eine einzelne Ressource geteilt, die verwaltet werden muss.

Es ist selten, dass man eine Singleton benötigen. Der Grund, warum sie schlecht sind, ist, dass sie wie ein global fühlen und sie sind ein voll einbezahlt Mitglied des GoF Design Patterns Buch.

Wenn Sie denken, Sie brauchen ein globales, sind Sie wahrscheinlich eine schreckliche Design Fehler zu machen.

Einige Codierung Snobs Blick nach unten auf sie als nur eine glorifizierte global. Auf die gleiche Art und Weise, dass viele Menschen hassen die goto Aussage gibt es andere, die Idee der jemals mit einem hate global . Ich habe mehr Entwickler zu außerordentlichen Längen gehen gesehen ein global zu vermeiden, weil sie als eine als Eingeständnis des Scheiterns verwenden. Seltsam aber wahr.

In der Praxis des Singleton Muster ist nur eine Programmiertechnik, die ein nützliches Teil Ihres Toolkit von Konzepten ist. Von Zeit zu Zeit kann es für Sie die ideale Lösung ist und es so verwenden. Aber es nur mit so können Sie prahlen mit einem Design-Muster ist genauso dumm, wie die Ablehnung immer, es zu benutzen, weil es nur ein global .

Misko Hevery, von Google, hat einige interessante Artikel über genau dieses Thema ...

Singletons sind Pathologische Liars eine Einheit hat Beispiel testen, die zeigt, wie Singletons kann es schwierig machen Abhängigkeitsketten, um herauszufinden, und starten oder eine Anwendung zu testen. Es ist ein ziemlich extremes Beispiel für Missbrauch, aber der Punkt, den er macht, ist nach wie vor gültig:

  

Singletons sind nichts anderes als globaler Zustand. Globaler Zustand macht es so Ihre Objekte heimlich halten, die Dinge können, die nicht in ihren APIs erklärt, und als Ergebnis, Singletons Ihre APIs in pathologische Lügner machen.

Wo sind die alle Singletons gegangen macht den Punkt, dass Dependency Injection gemacht hat es einfach Instanzen Konstrukteuren zu bekommen, die sie benötigen, die die zugrunde liegende Notwendigkeit hinter dem schlecht mildert, global Singletons verschrien im ersten Artikel.

Ich denke, die Verwirrung, die durch die Tatsache verursacht wird, dass die Menschen nicht wissen, die reale Anwendung der Singleton-Muster. Ich kann nicht genug betonen. Singleton ist nicht ein Muster Globals zu wickeln. Singleton Muster sollte nur das ein und nur eine Instanz einer bestimmten Klasse zu gewährleisten verwendet werden besteht während der Laufzeit.

Die Leute denken Singleton böse ist, weil sie es für Globals verwenden. Es ist wegen dieser Verwirrung, die Singleton auf sich herabsah. Bitte, nicht zu verwechseln Singletons und Globals. Wenn für den Zweck verwendet wurde es gedacht, Sie extreme Vorteile aus dem Singleton-Muster gewinnen.

Eine eher schlechte Sache über Singletons ist, dass man sie nicht sehr leicht erweitern kann. Sie haben grundsätzlich in irgendeiner Art von Dekorateur Muster oder so etwas zu bauen, wenn Sie ihre ändern möchten Verhalten. Auch, wenn Sie einen Tag mehr Möglichkeiten zu tun, dass eine Sache haben willst, kann es ziemlich schmerzhaft sein zu ändern, je nachdem, wie Sie Ihren Code legen.

Eine Sache zu beachten, wenn Sie Singletons DO verwenden, versuchen, sie zu passieren, um jeden, der sie braucht, anstatt sie direkt darauf zugreifen haben ... Ansonsten, wenn Sie jemals mehrere Möglichkeiten zu tun, das Ding haben entscheiden, dass Singletons der Fall ist, es wird ziemlich schwierig sein, da jede Klasse eine Abhängigkeit bettet sich zu ändern, wenn es direkt auf die Singleton zugreift.

Also im Grunde:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

statt:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

Ich glaube, diese Art von Mustern Dependency Injection genannt wird, und wird in der Regel eine gute Sache betrachtet.

Wie jedes Muster obwohl ... Denk darüber nach und prüfen, ob seine Verwendung in der gegebenen Situation nicht angemessen ist oder nicht ... Regeln besteht in der Regel gebrochen werden, und Muster sollte nicht nolens volens ohne Gedanken angewendet werden.

Das Singletonmuster ist kein Problem an sich. Das Problem ist, dass das Muster oft von Menschen entwickeln Software mit objektorientierten Werkzeugen ohne ein solides Verständnis der OO-Konzepte zu haben. Wenn Singletons in diesem Zusammenhang eingeführt werden, neigen sie dazu, in unüberschaubare Klassen zu wachsen, die Helfer Methoden für jede kleine Anwendung enthalten.

Singletons sind auch ein Problem aus der Perspektive des Testens. Sie neigen dazu, isolierte Einheit-Tests schwer zu schreiben zu machen. Inversion of Control (IOK) und dependency injection werden Muster gemeint, dieses Problem in einer objektorientierten Art und Weise zu überwinden, die sich Unit-Tests eignet .

In einem Müll gesammelt Umgebung Singletons schnell ein Problem hinsichtlich werden können Speicherverwaltung.

Es gibt auch das Multi-Threaded-Szenario, in dem Singletons einen Engpass sowie ein Synchronisierungsproblem werden kann.

wird ein Singleton implementiert eine statische Methode. Statische Methoden werden von Menschen vermieden, die Unit-Tests zu tun, weil sie nicht oder stubbed verspottet werden können. Die meisten Menschen auf dieser Seite sind große Befürworter der Unit-Tests. Die allgemein am meisten akzeptierte Konvention zu vermeiden, dass sie die Inversion of Control Muster verwendet wird.

Singletons sind auch schlecht, wenn es darum geht, Clustering . Denn dann haben Sie nicht „genau einen Singleton“ in Ihrer Anwendung mehr.

Betrachten Sie die folgende Situation: Als Entwickler haben Sie eine Web-Anwendung zu erstellen, die auf eine Datenbank zugreift. Um sicherzustellen, dass die gleichzeitige Datenbankaufrufe nicht miteinander in Konflikt stehen, erstellen Sie einen Thread-Save SingletonDao:

public class SingletonDao {
    // songleton's static variable and getInstance() method etc. omitted
    public void writeXYZ(...){
        synchronized(...){
            // some database writing operations...
        }
    }
}

So Sie sicher sind, dass nur ein Singleton in der Anwendung vorhanden ist und alle Datenbank gehen durch diese eine und einzige SingletonDao. Ihre Produktionsumgebung sieht nun wie folgt aus: Single Singleton

Es ist alles so weit in Ordnung.

Nun betrachten Sie mehrere Instanzen Ihrer Web-Anwendung in einem Cluster einrichten möchten. Nun haben Sie plötzlich so etwas wie folgt aus:

Viele Singletons

Das klingt seltsam, aber Sie jetzt in Ihrer Anwendung viele Singletons haben . Und das ist genau das, was ein Singleton nicht sein soll: viele Objekte davon zu haben. Dies ist besonders schlecht, wenn man, wie in diesem Beispiel gezeigt, wollen synchronisiert Anrufe an eine Datenbank machen.

Natürlich ist dies ein Beispiel für eine schlechte Nutzung eines Singleton. Aber die Botschaft dieses Beispiels ist. Sie können sich nicht darauf verlassen, dass es genau eine Instanz eines Singleton in Ihrer Anwendung - vor allem, wenn es um das Clustern kommt

  1. Es ist leicht (ab) als globale Variable verwendet.
  2. Klassen, die auf Singletons abhängig sind relativ schwieriger zu Unit-Test in der Isolation.

Monopoly ist der Teufel und Singletons mit Nicht-Nur-Lese / wandelbaren Zustand sind die 'echten' Problem ...

Nach dem Lesen Singletons sind Pathologische Liars wie in Jasons Antwort vorgeschlagen ich auf diese kleinen Leckerbissen kam, dass die besten präsentierte Beispiel wie bietet Singletons werden häufig missbraucht werden.

  

Global ist schlecht, weil:

     
      
  • a. Es bewirkt, dass Namespace Konflikt
  •   
  • b. Es setzt den Zustand in einer ungerechtfertigten Art und Weise
  •   
     

Wenn es um Singletons

     
      
  • a. Der explizite OO Weg, um sie zu rufen, verhindert, dass die Konflikte, so ein Punkt. ist kein Thema
  •   
  • b. Singletons ohne Zustand sind (wie Fabriken) sind kein Problem. Singletons mit Staat kann wieder in zwei Kategorien fallen, solche, die unveränderlich sind oder einmal schreiben und viele (config / Property-Dateien) lesen. Diese sind nicht schlecht. Mutable Singletons, die Art von Referenzhalter sind, sind diejenigen, die Sie sprechen von.
  •   

In der letzten Anweisung er mit Bezug auf das Konzept des Blog von ‚Singletons sind Lügner.‘

Wie wirkt sich das auf Monopoly anwenden?

Um ein Spiel des Monopols zu starten, zuerst:

  • wir die Regeln etablieren ersten, so dass jeder auf der gleichen Seite ist
  • alle eine gleiche Start zu Beginn des Spiels
  • gegeben
  • nur ein Satz von Regeln vorgestellt Verwirrung zu vermeiden
  • werden die Regeln nicht erlaubt während des Spiels zu ändern

Nun, für jeden, der nicht hat wirklich Monopol gespielt, sind diese Standards im besten Fall ideal. Eine Niederlage in Monopol ist schwer zu schlucken, weil das Monopol über Geld ist, wenn Sie verlieren Sie müssen das Spiel sorgfältig den Rest der Spieler beobachten zu beenden, und Verluste sind in der Regel schnell und vernichtend. Also, in der Regel die Regeln irgendwann verknotet das Eigeninteresse von einigen der Spieler auf Kosten des anderen zu dienen.

Sie sind also spielen Monopol mit Freunden Bob, Joe und Ed. Sie Ihr Reich schnell zu bauen und Marktanteil mit einer exponentiellen Rate raubend. Ihre Gegner zu schwächen und Sie beginnen, Blut zu riechen (bildlich). Ihr Kumpel Bob legte all sein Geld in so viele Low-Wert Eigenschaften wie möglich gridlocking aber sein ist kein hohen Return on Investment, wie er es erwartet zu empfangen. Bob, als Pech, landet auf dem Boardwalk und wird aus dem Spiel herausgeschnitten.

Jetzt geht das Spiel von freundlich zu ernster Angelegenheit Würfel-Rollen. Bob wurde das Beispiel des Scheiterns gemacht und Joe und Ed wollen nicht wie ‚der Kerl‘ enden. Also, der führende Spieler Sie sind, ganz plötzlich, wird der Feind. Joe und Ed anfangen zu üben under-the-table Werk, Hinter-dem-Rücken Geld Injektionen, unterbewertetes Haus-Swapping und in der Regel alles, was Sie als Spieler zu schwächen, bis einer von ihnen nach oben steigt.

Dann wird anstelle eines von ihnen zu gewinnen, der Prozess beginnt erneut. Ganz plötzlich wird eine endliche Menge von Regeln ein bewegliches Ziel und das Spiel artet in der Art der sozialen Interaktionen, die die Grundlage jeder Hoch bewertet Reality-TV-Show seit Survivor machen würde. Warum, weil die Regeln ändern sich und es gibt keinen Konsens darüber, wie / warum / was sie angeblich vertreten, und was noch wichtiger ist, es gibt keine Person, die Entscheidungen zu treffen. Jeder Spieler im Spiel, an diesem Punkt, wird seine / ihre eigenen Regeln machen und Chaos folgt, bis zwei der Spieler zu müde sind, um die Farce zu halten und langsam aufgeben.

Wenn also ein Regelwerk für ein Spiel genau einen Singleton dargestellt, würde das Monopol rulebook ein Beispiel für Missbrauch sein.

Wie wirkt sich das auf die Programmierung anwenden?

Abgesehen von all den offensichtlichen Thread-Sicherheit und Synchronisierungsprobleme that wandelbar Singletons vorhanden ... Wenn Sie einen Satz von Daten haben, dass in der Lage ist zu lesen / manipuliert von mehreren verschiedenen Quellen gleichzeitig und besteht während der gesamten Lebensdauer der Anwendungsausführung, es ist wahrscheinlich eine gute Zeit, einen Schritt zurück und frage: „Uhr ich mit der richtigen Art von Datenstruktur hier“.

Ich persönlich habe durch die Verwendung es als eine Art von Twisted Cross-Thread-Datenbankspeicher innerhalb einer Anwendung ein Programmierer Missbrauch eines Singletons gesehen. Ich kann direkt auf dem Code gearbeitet haben, zu bestätigen, dass es ein langsamer war (wegen der alle Gewindesicherungen erforderlich, um es Thread-sicher zu machen) und einem Alptraum zu arbeiten (wegen der unberechenbaren / intermittierender Art der Synchronisation Fehler), und fast unmöglich, unter ‚Produktion‘ Bedingungen zu testen. Sicher, könnte ein System entwickelt wurde, unter Verwendung von Polling / Signal einige der Performance-Probleme zu überwinden, aber das würde die Probleme mit dem Testen und nicht lösen, warum die Mühe, wenn eine ‚echte‘ Datenbank bereits die gleiche Funktionalität in einem wesentlich robusten erreichen kann / skalierbare Art und Weise.

Ein Singleton ist nur eine Option, wenn Sie brauchen, was ein Singleton bietet. Eine Zuschreibung einer Nur-Lese-Instanz eines Objekts. Die gleiche Regel wie auch auf die Eigenschaften / Mitglieder des Objekts Kaskade sollte.

Singleton geht es nicht um einzelne Instanz!

Im Gegensatz zu anderen Antworten, die ich will nicht darüber reden, was ist falsch mit Singletons aber Ihnen zu zeigen, wie mächtig und genial sie sind, wenn richtig verwendet!

  • Problem : Singleton kann eine Herausforderung in Multi-Threading-Umgebung
    sein Lösung : a. Single-Threaded-Bootstrap-Prozess Verwenden Sie alle Abhängigkeiten Ihrer Singleton zu initialisieren
  • Problem : Es ist schwer, Singletons zu verspotten
    . Lösung : Verwenden Sie die Methode Fabrik Muster für spöttische
    MyModel myModel = Factory.inject(MyModel.class); Sie können Karte MyModel Klasse TestMyModel, die es erbt, überall wenn MyModel Sie TestMyModel instread injiziert wird erhalten.
  • Problem : Singletons kann Gedächtnis Lauch verursachen, da sie nie entsorgt
    . Lösung : Nun, entsorgen Sie sie! Implementieren Sie einen Rückruf in Ihrer App richtig einen Singletons zu verfügen, sollten Sie alle Daten entfernen, um sie verknüpfen und schließlich: entferne sie aus der Fabrik.

Wie ich auf den Titel Singleton angegeben sind nicht etwa einzelne Instanz.

  • Singletons verbessert die Lesbarkeit . Sie zu Ihrer Klasse schauen und sehen, was Singletons es herauszufinden injiziert, was ist es Abhängigkeiten
  • Singletons verbessert Wartung : Wenn Sie eine Abhängigkeit von einer Klasse entfernen Sie nur einige Singleton Injektion gelöscht, brauchen Sie keine große Verbindung von anderen Klassen, die gerade bewegte Ihre Abhängigkeit gehen um und bearbeiten (Dies ist stinkender Code für mich @ Jim Burger )
  • Singletons verbessert das Gedächtnis und die Leistung : Wenn geschieht etwas, was in der Anwendung, und es dauert eine lange Kette von Rückrufen zu liefern, Sie Speicher und Leistung verschwenden, von Singleton verwenden Sie die Mitte schneiden Mann, und Ihre Leistung und Speichernutzung verbessern (durch unnötige lokale Variablen Zuweisungen vermieden wird).

Meine Antwort auf die Frage, wie schlecht Singletons sind, lautet immer: „Es ist schwer, sie richtig zu machen.“Viele der grundlegenden Komponenten von Sprachen sind Singletons (Klassen, Funktionen, Namespaces und sogar Operatoren), ebenso wie Komponenten in anderen Aspekten der Datenverarbeitung (localhost, Standardroute, virtuelles Dateisystem usw.), und das ist kein Zufall.Während sie von Zeit zu Zeit Ärger und Frustration verursachen, können sie auch dafür sorgen, dass viele Dinge VIEL besser funktionieren.

Die beiden größten Fehler, die ich sehe, sind:Behandeln Sie es wie ein globales Element und definieren Sie den Singleton-Abschluss nicht.

Alle reden von Singletons als Globals, weil das im Grunde genommen so ist.Viele (leider nicht alle) Nachteile eines Globals liegen jedoch nicht unbedingt darin, dass er global ist, sondern darin, wie man ihn nutzt.Das Gleiche gilt für Singletons.Eigentlich umso mehr, als „einzelne Instanz“ wirklich nicht „global zugänglich“ bedeuten muss.Es handelt sich eher um ein natürliches Nebenprodukt, und angesichts all des Bösen, von dem wir wissen, dass es daraus entsteht, sollten wir es nicht so eilig haben, die globale Zugänglichkeit auszunutzen.Sobald Programmierer einen Singleton sehen, scheinen sie immer direkt über seine Instanzmethode darauf zuzugreifen.Stattdessen sollten Sie wie zu jedem anderen Objekt dorthin navigieren.Der meiste Code sollte sich nicht einmal bewusst sein, dass es sich um einen Singleton handelt (lose Kopplung, oder?).Wenn nur ein kleiner Teil des Codes auf das Objekt zugreift, als wäre es ein globales Objekt, wird großer Schaden rückgängig gemacht.Ich empfehle, dies durchzusetzen, indem der Zugriff auf die Instanzfunktion eingeschränkt wird.

Der Singleton-Kontext ist ebenfalls sehr wichtig.Das bestimmende Merkmal eines Singletons ist, dass es „nur einen“ gibt, aber die Wahrheit ist, dass es „nur einen“ innerhalb einer Art Kontext/Namensraum gibt.Sie sind normalerweise einer von:eine pro Thread, Prozess, IP-Adresse oder Cluster, kann aber auch eine pro Prozessor, Maschine, Sprach-Namespace/Klassenlader/was auch immer, Subnetz, Internet usw. sein.

Der andere, weniger häufige Fehler besteht darin, den Singleton-Lebensstil zu ignorieren.Nur weil es nur eines gibt, bedeutet das nicht, dass ein Singleton irgendein allmächtiges „war immer war und immer sein wird“, und es ist auch nicht allgemein wünschenswert (Objekte ohne Anfang und Ende verstoßen gegen alle möglichen nützlichen Annahmen im Code und sollten nur verwendet werden unter den verzweifeltsten Umständen.

Wenn Sie diese Fehler vermeiden, können Singletons immer noch ein PITA sein, aber es ist bereit zu sehen, dass viele der schlimmsten Probleme deutlich gemildert werden.Stellen Sie sich einen Java Singleton vor, der explizit als einmal pro Klassenlader definiert ist (was bedeutet, dass er eine Thread-Sicherheitsrichtlinie benötigt), mit definierten Erstellungs- und Zerstörungsmethoden und einem Lebenszyklus, der vorschreibt, wann und wie sie aufgerufen werden, und dessen „Instanz“-Methode vorhanden ist Paketschutz, sodass der Zugriff im Allgemeinen über andere, nicht globale Objekte erfolgt.Immer noch eine potenzielle Problemquelle, aber sicherlich viel weniger Ärger.

Traurigerweise, anstatt gute Beispiele dafür zu vermitteln, wie man Singletons macht.Wir lehren schlechte Beispiele, lassen Programmierer eine Zeit lang damit herumlaufen und sagen ihnen dann, dass es sich um ein schlechtes Entwurfsmuster handelt.

Siehe Wikipedia Singleton_pattern

  

Es ist auch ein Anti-Muster von einigen Leuten, die das Gefühl der Ansicht, dass es übermäßig verwendet wird, unnötige Einschränkungen in Situationen einzuführen, wo eine einzige Instanz einer Klasse nicht tatsächlich erforderlich ist. [1] [2] [3] [ 4]

Referenzen (nur relevant Referenzen aus dem Artikel)

  1. ^ Alex Miller. Patterns Ich hasse # 1: Singleton Juli 2007
  2. ^ Scott Densmore. Warum Singletons sind böse Mai 2004
  3. ^ Steve Yegge. Singletons als dumm September 2004
  4. ^ J. B. Rainsberger, IBM. Verwenden Sie Ihre Singletons weise Juli 2001

Es ist nicht, dass Singletons selbst ist schlecht, aber das GoF Entwurfsmuster ist. Das einzige wirklich Argument, das gültig ist, ist, dass die GoF-Entwurfsmuster eignet sich nicht in Bezug auf die Prüfung, vor allem, wenn Tests parallel ausgeführt werden.

Mit einer einzigen Instanz einer Klasse ist ein gültiges Konstrukt, solange Sie die folgenden Mittel in Code anwenden:

  1. Stellen Sie sicher, dass die Klasse, die als Singleton verwendet wird, eine Schnittstelle implementiert. Auf diese Weise können Stubs oder Mocks mit der gleichen Schnittstelle implementiert werden

  2. Stellen Sie sicher, dass das Singleton Thread-sicher ist. Das ist eine Selbstverständlichkeit.

  3. Die Singleton sollte in der Natur und nicht zu kompliziert einfach sein.

  4. Während der Laufzeit der Sie Anwendung, wo Singletons müssen ein bestimmtes Objekt übergeben werden, eine Klasse Fabrik verwenden, die das Objekt baut und die Klasse Fabrik haben die Singleton-Instanz der Klasse übergeben, die es braucht.

  5. Während des Tests und deterministisches Verhalten zu gewährleisten, erstellen Sie die Singleton-Klasse als separate Instanz entweder die tatsächliche Klasse selbst oder einen Stub / Mock, die sein Verhalten implementiert und gibt sie in Bezug auf die Klasse ist, die es erfordert. verwenden, um die Klasse Faktor nicht, dass das Objekt unter Test erstellt, die die Singleton während des Tests benötigt, da es die einzige globale Instanz davon passieren, die den Zweck besiegt.

Wir haben Singletons in unseren Lösungen mit grossem Erfolg eingesetzt, die parallel Testlauf Strömen prüfbar gewährleistet deterministisches Verhalten sind.

Vince Huston diese Kriterien hat, die mir sinnvoll erscheinen:

  

Singleton sollte nur in Betracht gezogen werden, wenn alle drei der folgenden Kriterien erfüllt sind:

     
      
  • Der Besitz der einzigen Instanz nicht angemessen zugeordnet werden
  •   
  • Verzögerte Initialisierung ist wünschenswert
  •   
  • Globaler Zugriff soweit nicht anderweitig vorgesehen
  •   
     

Wenn das Eigentum an der einzigen Instanz, wann und wie die Initialisierung auftritt, und die globale Zugriff sind keine Fragen, Singleton ist nicht interessant genug.

Ich möchte die vier Punkte in der akzeptierte Antwort adressieren, kann hoffentlich jemand erklären, warum ich falsch liege.

  1. Warum Abhängigkeiten in Ihrem Code schlecht versteckt? Es gibt bereits Dutzende von versteckten Abhängigkeiten (C Runtime-Anrufe, OS-API-Aufrufe, die globalen Funktionsaufrufe) und Singleton Abhängigkeiten sind leicht zu finden (Suche zum Beispiel ()).

    „Making etwas global zu vermeiden vorbei es sich um einen Code Geruch ist.“ Warum vergeht etwas nicht um zu vermeiden, dass es ein Singleton ein Code Geruch zu machen?

    Wenn Sie ein Objekt durch 10 Funktionen in einem Call-Stack vorbei sind nur einen Singleton zu vermeiden, ist das so groß?

  2. Single Prinzip Verantwortung: Ich denke, das ist ein bisschen vage und hängt von Ihrer Definition von Verantwortung. Eine relevante Frage wäre, warum das Hinzufügen dieser spezifische "Verantwortung" zu einer Klasse Angelegenheit?

  3. Warum zu einer Klasse ein Objekt nicht vorbei macht es eng gekoppelt als das Objekt als Singleton von innerhalb der Klasse mit?

  4. Warum es ändern, wie lange der Zustand dauert? Singletons können manuell erstellt oder zerstört werden, so dass die Steuerung immer noch da, und Sie können die Lebensdauer der gleiche wie ein Nicht-Singleton-Objekt Lebenszeit wäre machen.

In Bezug auf Unit-Tests:

  • nicht alle Klassen müssen Einheit sein getestet
  • nicht alle Klassen, die Einheit sein müssen getestet Notwendigkeit der Änderungen Umsetzung des Singletons
  • , wenn sie Sie muss sein Gerät getestet und brauchen die Umsetzung zu ändern, es ist einfach eine Klasse zu ändern aus Verwendung eines Singleton die zu mit Singletons weitergegeben, um es über die Abhängigkeit Injektion.

Ich bin nicht auf das gut / bösen Argumente Kommentar zu gehen, aber ich habe sie nicht da? Frühling kam. Mit Dependency Injection ziemlich meine Anforderungen entfernt hat für Singleton, servicelocators und Fabriken. Ich finde das eine sehr viel produktive und saubere Umwelt, zumindest für die Art der Arbeit, die ich tue (Java-basierte Web-Anwendungen).

Es ist nichts falsch mit dem Muster, vorausgesetzt, es ist für einen bestimmten Aspekt des Modells verwendet wird, die wirklich einzige ist.

ich glaube, das Spiel zu seinem übermäßigen Gebrauch zurückzuführen ist, die wiederum aufgrund der Tatsache ist, dass es das einfachste Muster ist zu verstehen und umzusetzen.

Singletons sind schlecht von einer puristischen Sicht.

Aus pratical Sicht ein Singleton ist ein Trade-off Zeit vs Komplexität der Entwicklung .

Wenn Sie Ihre Anwendung wird nicht wissen, dass viel ändern sie sind ziemlich OK zu gehen. Genau wissen, dass Sie die Dinge Refactoring müssen, wenn Ihre Anforderungen auf unerwartete Weise ändern (was in den meisten Fällen ziemlich in Ordnung ist).

kann

Singletons manchmal auch Unit-Tests erschweren.

Singleton ein Muster ist, und kann wie jedes andere Werkzeug verwendet oder missbraucht werden.

Der schlechte Teil eines Singleton ist in der Regel die Benutzer (oder soll ich sagen, die unangemessene Verwendung eines Singletons für Dinge, die es nicht tun soll). Der größte Täter einen Singleton als Fälschung globaler Variable verwendet wird.

Wenn Sie Code unter Verwendung von Singletons schreiben, sagen, ein Logger oder eine Datenbankverbindung, und danach Sie entdecken, was Sie brauchen mehr als ein Protokoll oder mehr als eine Datenbank, bist du in Schwierigkeiten.

Singletons machen es sehr schwer, um von ihnen zu regelmäßigen Objekten zu bewegen.

Außerdem ist es auch einfach, ein nicht-Thread-sicher Singletons zu schreiben.

Anstatt Singletons verwenden, sollten Sie alle benötigten Gebrauchsgegenstände von Funktion Funktion übergeben. Das kann vereinfacht werden, wenn Sie alle sie in ein Hilfsobjekt wickeln, wie folgt aus:

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}

Die Probleme mit Singletons ist die Frage der Erhöhung der Reichweite und daher Kopplung . Es ist nicht zu leugnen, dass es einige Situationen, in denen Sie den Zugriff tun müssen, um eine einzelne Instanz, und es kann auch andere Arten erreicht werden.

Ich ziehe es jetzt um eine Inversion of Control (IOK) Behälter zu entwerfen und ermöglichen, die die Lebensdauern durch den Behälter zu steuern. Dies bietet Ihnen den Vorteil der Klassen, die auf der Instanz abhängen keine Kenntnis von der Tatsache, dass es nur eine Instanz ist. Die Lebensdauer des Singletons kann in Zukunft geändert werden. Sobald ein solches Beispiel traf ich kürzlich eine einfache Einstellung von Single-Threaded war multi-threaded.

FWIW, wenn es sich um eine PIA, wenn Sie Unit-Test versuchen, es es dann zu PIA zu gehen, wenn Sie debuggen, Fehler zu beheben versuchen, oder es zu verbessern.

Neue Artikel zu diesem Thema von Chris Reath unter Coding Ohne Kommentare .

Hinweis: Codierung ohne Kommentare ist nicht mehr gültig. Der Artikel wurde jedoch im Zusammenhang mit von einem anderen Benutzer geklont worden.

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

Hier ist eine weitere Sache, über Singletons, die niemand sagte noch.

In den meisten Fällen „singletonity“ ist ein Detail der Umsetzung für einige Klasse statt charakteristisch für seine Schnittstelle. Inversion of Control Container können diese Eigenschaft aus der Klasse Benutzer verbergen; Sie müssen nur Ihre Klasse als Singleton (zum Beispiel in Java mit @Singleton Anmerkung) markieren, und das ist es; IOCC wird den Rest erledigen. Sie brauchen nicht den globalen Zugriff auf Ihre Singleton-Instanz zu schaffen, da der Zugriff bereits von IOCC verwaltet wird. So gibt es nichts falsch mit IoC Singletons.

GoF Singletons im Gegensatz zu IoC Singletons sollen "singletonity" in der Schnittstelle, über getInstance () -Methode, entlarven und so, dass sie leiden an alles gesagt über.

Singletons sind nicht schlecht. Es ist nur schlecht, wenn man etwas global einzigartig machen, die nicht global eindeutig ist.

Es gibt jedoch „Anwendungsbereich Dienste“ (man denke über ein Messaging-System, das Komponenten interagieren macht) - Dies erfordert eine Singleton, ein „Message.“ - Klasse, die eine Methode „Sendmessage (...)“ hat

Sie können dann folgendermaßen aus der ganzen Ort:

MessageQueue.Current.SendMessage (neu MailArrivedMessage (...));

Und natürlich tun:

MessageQueue.Current.RegisterReceiver (this);

in Klassen, die IMessageReceiver implementieren.

Zu viele Menschen setzen Objekte, die nicht sicher in einem Singletonmuster Gewinde sind. Ich habe Beispiele für einen Datacontext gesehen ( LINQ to SQL ) getan in einem Singletonmuster, trotz der Tatsache, dass die Datacontext nicht sicher ist, fädeln und ist eine reine Einheit-of-Arbeitsobjekt.

Weil sie im Grunde globale Variablen objektorientiert sind, können Sie in der Regel entwerfen Sie Ihre Klassen so, damit Sie sie nicht brauchen.

Ein Muster entsteht, wenn mehrere Personen (oder Teams) auf ähnliche oder identische Lösungen ankommt. Viele Leute verwenden noch Singletons in ihrer ursprünglichen Form oder mit Fabrik-Vorlagen (gute Diskussion in Alexandrescu Modern C ++ Design). Concurrency und Schwierigkeiten bei der Verwaltung der Lebensdauer des Objekts sind die Haupthindernisse, mit den ehemaligen einfach zu verwaltenden, wie Sie vorschlagen.

Wie alle Entscheidungen hat Singleton seinen fairen Anteil an Höhen und Tiefen. Ich denke, sie können in Maßen verwendet werden, insbesondere für Objekte, die die Anwendung Lebensdauer überleben. Die Tatsache, dass sie ähneln (und wahrscheinlich) Globals haben vermutlich die Puristen auf den Weg.

Zum einen eine Klasse und ihre Mitarbeiter sollten zunächst ihren beabsichtigten Zweck erfüllen, anstatt auf deoendents konzentriert. Lifecycle Management (wenn Instanzen creared snd, wenn sie sich außerhalb des Geltungsbereichs gehen) sollte nicht Teil der cladses Verantwortung. Die akzeptierte Best Practice dafür ist, Handwerk oder eine neue Komponente konfigurieren Abhängigkeiten Injektion mit Abhängigkeit zu verwalten.

Oft Software wird komplizierter es sinnvoll, mehrere unabhängigen Instanzen der „Singletons“ Klasse mit unterschiedlichem Zustand zu haben macht. Begehen Code die Singleton einfach zu greifen, ist falsch in solchen Fällen. Mit Singleton.getInstance () könnte für kleine einfache Systeme ok sein, aber es funktioniert nicht / Skala, wenn man könnte eine andere Instanz derselben Klasse benötigen.

sollte keine Klasse gedacht werden als Singleton, sondern, dass eine Anwendung, sollte es Nutzung ist oder wie es verwendet Bliebene zu konfigurieren. Für eine schnelle und böse nicht nur luke Hardcoding nicht-Materie sagen Dateipfade nicht aber für größere Anwendungen keine Rolle benötigen solche Abhängigkeiten werden herausgerechnet und in angemessener Art und Weise unter Verwendung von DI verwaltet werden.

Die Probleme, die Singleton Ursache in der Prüfung ist ein Symptom für ihre harten einzigen Anwendungsfall / Umwelt codiert. Die Test-Suite und die viele Tests sind jedes einzeln und getrennt etwas, das nicht kompatibel mit hartzucodieren einen Singleton ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top