Das Singleton-Muster ist ein voll bezahltes Mitglied des Musterbuchs des GoF , scheint aber in letzter Zeit von der Entwicklerwelt eher verwaist zu sein. Ich verwende immer noch ziemlich viele Singletons, insbesondere für Factory-Klassen , und obwohl Sie bei Multithreading-Problemen (wie bei jeder Klasse tatsächlich) etwas vorsichtig sein müssen, verstehe ich nicht, warum sie so schrecklich sind.
Insbesondere der Stapelüberlauf scheint davon auszugehen, dass alle der Meinung sind, dass Singletons böse sind. Warum?
Bitte unterstützen Sie Ihre Antworten mit " Fakten, Referenzen oder spezifischem Fachwissen ".
Antworten:
Umschrieben von Brian Button:
Sie werden im Allgemeinen als globale Instanz verwendet. Warum ist das so schlimm? Weil Sie die Abhängigkeiten Ihrer Anwendung in Ihrem Code verbergen, anstatt sie über die Schnittstellen verfügbar zu machen. Etwas global zu machen, um es nicht weiterzugeben, ist ein Codegeruch .
Sie verstoßen gegen das Prinzip der Einzelverantwortung : Sie kontrollieren ihre eigene Schöpfung und ihren eigenen Lebenszyklus.
Sie bewirken von Natur aus, dass Code eng gekoppelt ist . Dies macht es in vielen Fällen ziemlich schwierig, sie im Test vorzutäuschen.
Sie tragen den Zustand für die Lebensdauer der Anwendung. Ein weiterer Erfolg beim Testen, da Sie in einer Situation enden können, in der Tests bestellt werden müssen, was ein großes Nein Nein für Komponententests ist. Warum? Weil jeder Unit-Test unabhängig vom anderen sein sollte.
quelle
Singletons lösen ein (und nur ein) Problem.
Ressourcenkonflikt.
Wenn Sie eine Ressource haben, die
( 1 ) kann nur eine einzige Instanz haben, und
( 2 ) Sie müssen diese einzelne Instanz verwalten.
Du brauchst einen Singleton .
Es gibt nicht viele Beispiele. Eine Protokolldatei ist die große. Sie möchten nicht nur eine einzelne Protokolldatei verlassen. Sie möchten es richtig spülen, synchronisieren und schließen. Dies ist ein Beispiel für eine einzelne gemeinsam genutzte Ressource, die verwaltet werden muss.
Es ist selten, dass Sie einen Singleton benötigen. Der Grund, warum sie schlecht sind, ist, dass sie sich wie ein Global fühlen und ein voll bezahltes Mitglied des GoF Design Patterns- Buches sind.
Wenn Sie denken, Sie brauchen eine globale, machen Sie wahrscheinlich einen schrecklichen Designfehler.
quelle
Einige Coding-Snobs sehen sie nur als verherrlichte Welt an. So wie viele Menschen die goto- Aussage hassen , gibt es auch andere, die die Idee hassen, jemals eine globale zu verwenden . Ich habe gesehen, dass mehrere Entwickler außerordentliche Anstrengungen unternommen haben, um ein globales Problem zu vermeiden, weil sie erwogen haben, eines als Eingeständnis für einen Fehler zu verwenden. Komisch aber wahr.
In der Praxis ist das Singleton- Muster nur eine Programmiertechnik, die ein nützlicher Bestandteil Ihres Toolkits an Konzepten ist. Von Zeit zu Zeit finden Sie vielleicht, dass es die ideale Lösung ist, und verwenden Sie es daher. Aber es nur zu verwenden, damit Sie sich rühmen können, ein Designmuster zu verwenden, ist genauso dumm, wie sich zu weigern, es jemals zu verwenden, weil es nur ein globales Muster ist .
quelle
Misko Hevery von Google hat einige interessante Artikel zu genau diesem Thema ...
Singletons sind pathologische Lügner Ein Beispiel für Unit-Tests zeigt, wie Singletons es schwierig machen können, Abhängigkeitsketten herauszufinden und eine Anwendung zu starten oder zu testen. Es ist ein ziemlich extremes Beispiel für Missbrauch, aber der Punkt, den er macht, ist immer noch gültig:
Wo alle Singletons verschwunden sind, wird darauf hingewiesen, dass die Abhängigkeitsinjektion es einfach gemacht hat, Instanzen zu Konstruktoren zu bringen, die sie benötigen, was den zugrunde liegenden Bedarf hinter den schlechten, globalen Singletons, die im ersten Artikel beschrieben wurden, verringert.
quelle
Ich denke, die Verwirrung wird durch die Tatsache verursacht, dass die Leute die wirkliche Anwendung des Singleton-Musters nicht kennen. Ich kann das nicht genug betonen. Singleton ist kein Muster zum Umwickeln von Globalen. Das Singleton-Muster sollte nur verwendet werden, um sicherzustellen, dass zur Laufzeit nur eine Instanz einer bestimmten Klasse vorhanden ist.
Die Leute denken, Singleton sei böse, weil sie es für Globals verwenden. Aufgrund dieser Verwirrung wird auf Singleton herabgesehen. Bitte verwechseln Sie Singletons und Globals nicht. Wenn Sie es für den Zweck verwenden, für den es bestimmt war, profitieren Sie extrem vom Singleton-Muster.
quelle
setInstance
Methoden gesehen .) Das spielt jedoch kaum eine Rolle - das Weenie, das einen Singleton "brauchte", wusste auch nichts über Kapselung oder was falsch ist veränderlicher globaler Staat, also stellte er hilfreich (?) Setter für jeden zur Verfügung. Single. Feld. (Und ja, das passiert.goto
usw. Sie funktionieren möglicherweise in vielen Fällen, aber ehrlich gesagt reicht "funktioniert" nicht aus - wenn Sie gegen die konventionelle Weisheit verstoßen möchten, sollten Sie besser in der Lage sein, zu demonstrieren, wie Sie vorgehen ist besser als die herkömmlichen Lösungen. Und ich habe noch keinen solchen Fall für das Singleton-Muster gesehen.getInstance
oder eine ähnlich benannte Methode verfügbar macht und die Existenz von a verhindert zweite Instanz. Ehrlich gesagt, könnten Sie zu diesem Zeitpunkt genauso gut nicht einmal die eine Instanz haben.Eine ziemlich schlechte Sache bei Singletons ist, dass man sie nicht so einfach erweitern kann. Sie müssen im Grunde eine Art Dekorationsmuster einbauen oder ähnliches einbauen, wenn Sie ihr Verhalten ändern möchten. Wenn Sie eines Tages mehrere Möglichkeiten haben möchten, dies zu tun, kann es ziemlich schmerzhaft sein, Änderungen vorzunehmen, je nachdem, wie Sie Ihren Code gestalten.
Eine Sache, die Sie beachten sollten: Wenn Sie Singletons verwenden, versuchen Sie, diese an diejenigen weiterzugeben, die sie benötigen, anstatt sie direkt darauf zugreifen zu lassen. Andernfalls können Sie das tun, was Singleton tut Es ist ziemlich schwierig zu ändern, da jede Klasse eine Abhängigkeit einbettet, wenn sie direkt auf den Singleton zugreift.
Also im Grunde genommen:
eher, als:
Ich glaube, diese Art von Muster wird als Abhängigkeitsinjektion bezeichnet und allgemein als eine gute Sache angesehen.
Wie jedes Muster auch ... Denken Sie darüber nach und überlegen Sie, ob seine Verwendung in der gegebenen Situation unangemessen ist oder nicht ... Regeln gelten normalerweise als gebrochen, und Muster sollten nicht ohne nachzudenken angewendet werden.
quelle
getInstance()
, ist (b) nicht mehr ganz richtig.getInstance()
, haben Sie den einen nützlichen Unterschied zwischen dem Singleton-Muster und einer gewöhnlichen Referenz effektiv beseitigt. Für den Rest des Codes ist Singleness keine Eigenschaft mehr. Nur der Anrufer von mussgetInstance()
jemals wissen oder sich sogar darum kümmern, wie viele Instanzen es gibt. Mit nur einem Anrufer kostet es die Klasse mehr Aufwand und Flexibilität, die Singleness zuverlässig durchzusetzen, als wenn der Anrufer einfach eine Referenz speichert und wiederverwendet.Das Singleton-Muster ist an sich kein Problem. Das Problem ist, dass das Muster häufig von Personen verwendet wird, die Software mit objektorientierten Tools entwickeln, ohne die OO-Konzepte genau zu verstehen. Wenn Singletons in diesem Zusammenhang eingeführt werden, neigen sie dazu, zu nicht verwaltbaren Klassen zu werden, die Hilfsmethoden für jede kleine Verwendung enthalten.
Singletons sind auch aus Testsicht ein Problem. Sie neigen dazu, isolierte Unit-Tests schwer zu schreiben. Inversion of Control (IoC) und Dependency Injection sind Muster, mit denen dieses Problem objektorientiert überwunden werden soll und die sich für Unit-Tests eignen.
In einer Müllsammelumgebung können Singletons schnell zu einem Problem bei der Speicherverwaltung werden.
Es gibt auch das Multithread-Szenario, in dem Singletons sowohl zu einem Engpass als auch zu einem Synchronisationsproblem werden können.
quelle
Ein Singleton wird mit einer statischen Methode implementiert. Statische Methoden werden von Personen vermieden, die Unit-Tests durchführen, da sie nicht verspottet oder gestoppt werden können. Die meisten Leute auf dieser Seite sind große Befürworter von Unit-Tests. Die allgemein am meisten akzeptierte Konvention, um sie zu vermeiden, ist die Inversion des Kontrollmusters .
quelle
Singleton
Klasse testen . Dies erschwert jedoch den Testprozess immens. Zum einen müssen Sie jetzt in der Lage sein, Klassen nach Belieben zu entladen (in den meisten Sprachen nicht wirklich eine Option) oder für jeden Test eine neue VM zu starten (lesen Sie: Tests können tausende Male so lange dauern). Für zwei ist die Abhängigkeit vonSingleton
jedoch ein Implementierungsdetail, das jetzt in allen Ihren Tests verloren geht.Singletons sind auch schlecht, wenn es um Clustering geht . Denn dann haben Sie nicht mehr "genau einen Singleton" in Ihrer Anwendung.
Stellen Sie sich folgende Situation vor: Als Entwickler müssen Sie eine Webanwendung erstellen, die auf eine Datenbank zugreift. Um sicherzustellen, dass gleichzeitige Datenbankaufrufe nicht in Konflikt miteinander stehen, erstellen Sie einen Thread-Save
SingletonDao
:Sie sind also sicher, dass nur ein Singleton in Ihrer Anwendung vorhanden ist und alle Datenbanken diesen einzigen durchlaufen
SingletonDao
. Ihre Produktionsumgebung sieht jetzt folgendermaßen aus:Bisher ist alles in Ordnung.
Stellen Sie sich nun vor, Sie möchten mehrere Instanzen Ihrer Webanwendung in einem Cluster einrichten. Jetzt haben Sie plötzlich so etwas:
Das klingt komisch, aber jetzt haben Sie viele Singletons in Ihrer Anwendung . Und genau das soll ein Singleton nicht sein: Viele Objekte davon haben. Dies ist besonders schlimm, wenn Sie, wie in diesem Beispiel gezeigt, synchronisierte Aufrufe an eine Datenbank tätigen möchten.
Dies ist natürlich ein Beispiel für eine schlechte Verwendung eines Singletons. Die Meldung in diesem Beispiel lautet jedoch: Sie können sich nicht darauf verlassen, dass Ihre Anwendung genau eine Instanz eines Singletons enthält - insbesondere beim Clustering.
quelle
quelle
Monopol ist der Teufel und Singletons mit nicht schreibgeschütztem / veränderlichem Zustand sind das "wahre" Problem ...
Nachdem ich gelesen hatte, dass Singletons pathologische Lügner sind, wie in Jasons Antwort vorgeschlagen, stieß ich auf diesen kleinen Leckerbissen, der das am besten präsentierte Beispiel dafür liefert, wie Singletons oft missbraucht werden.
In der letzten Aussage bezieht er sich auf das Konzept des Blogs "Singletons sind Lügner".
Wie trifft dies auf Monopoly zu?
Um ein Monopolspiel zu beginnen, zuerst:
Für alle, die nicht wirklich Monopol gespielt haben, sind diese Standards bestenfalls ideal. Eine Niederlage im Monopol ist schwer zu schlucken, denn beim Monopol geht es um Geld. Wenn Sie verlieren, müssen Sie akribisch zusehen, wie der Rest der Spieler das Spiel beendet, und die Verluste sind normalerweise schnell und erdrückend. Daher werden die Regeln normalerweise irgendwann verdreht, um dem Eigeninteresse einiger Spieler auf Kosten der anderen zu dienen.
Sie spielen also das Monopol mit den Freunden Bob, Joe und Ed. Sie bauen schnell Ihr Imperium auf und verbrauchen exponentiell Marktanteile. Ihre Gegner werden schwächer und Sie beginnen (im übertragenen Sinne) Blut zu riechen. Ihr Kumpel Bob hat sein ganzes Geld in die Blockade so vieler minderwertiger Immobilien wie möglich gesteckt, aber er erhält nicht die erwartete hohe Kapitalrendite. Bob landet als Pech auf Ihrem Boardwalk und wird aus dem Spiel ausgeschlossen.
Jetzt geht das Spiel vom freundlichen Würfeln zum ernsthaften Geschäft. Bob wurde zum Beispiel des Scheiterns gemacht und Joe und Ed wollen nicht wie 'dieser Typ' enden. Als führender Spieler werden Sie plötzlich zum Feind. Joe und Ed üben unter dem Tisch Trades, Geldspritzen hinter dem Rücken, unterbewerteten Haustausch und im Allgemeinen alles, was Sie als Spieler schwächt, bis einer von ihnen an die Spitze steigt.
Anstatt dass einer von ihnen gewinnt, beginnt der Prozess von vorne. Plötzlich wird ein endliches Regelwerk zu einem beweglichen Ziel und das Spiel degeneriert zu einer Art sozialer Interaktion, die die Grundlage jeder hoch bewerteten Reality-TV-Show seit Survivor bilden würde. Warum, weil sich die Regeln ändern und es keinen Konsens darüber gibt, wie / warum / was sie darstellen sollen, und was noch wichtiger ist, dass niemand die Entscheidungen trifft. Zu diesem Zeitpunkt stellt jeder Spieler im Spiel seine eigenen Regeln auf und es kommt zu Chaos, bis zwei der Spieler zu müde sind, um die Scharade aufrechtzuerhalten und langsam aufzugeben.
Wenn also ein Regelbuch für ein Spiel genau einen Singleton darstellt, wäre das Monopol-Regelbuch ein Beispiel für Missbrauch.
Wie trifft dies auf die Programmierung zu?
Abgesehen von all den offensichtlichen Thread-Sicherheits- und Synchronisationsproblemen, die bei veränderlichen Singletons auftreten ... Wenn Sie über einen Datensatz verfügen, der von mehreren verschiedenen Quellen gleichzeitig gelesen / bearbeitet werden kann und während der Lebensdauer der Anwendungsausführung besteht, Es ist wahrscheinlich ein guter Zeitpunkt, einen Schritt zurückzutreten und zu fragen, ob ich hier die richtige Art von Datenstruktur verwende.
Persönlich habe ich gesehen, wie ein Programmierer einen Singleton missbraucht, indem er ihn als eine Art verdrehten Cross-Thread-Datenbankspeicher in einer Anwendung verwendet. Nachdem ich direkt an dem Code gearbeitet habe, kann ich bestätigen, dass er langsam war (wegen all der Thread-Sperren, die erforderlich sind, um ihn threadsicher zu machen) und ein Albtraum war, an dem gearbeitet werden musste (wegen der unvorhersehbaren / intermittierenden Natur von Synchronisationsfehlern) Unter Produktionsbedingungen kaum zu testen. Sicher, ein System hätte mithilfe von Polling / Signaling entwickelt werden können, um einige der Leistungsprobleme zu überwinden, aber das würde die Probleme beim Testen nicht lösen, und warum sollte man sich die Mühe machen, wenn eine "echte" Datenbank bereits die gleiche Funktionalität in einer viel robusteren Version erreichen kann? / skalierbare Weise.
Ein Singleton ist nur dann eine Option, wenn Sie das benötigen, was ein Singleton bietet. Eine schreibgeschützte Instanz eines Objekts. Dieselbe Regel sollte auch für die Eigenschaften / Elemente des Objekts gelten.
quelle
Singleton.getInstance()
. Eine Sprache, die Reflexion unterstützt, kann dies möglicherweise umgehen, indem Sie das Feld festlegen, in dem die One True Instance gespeichert ist. IMO, Tests werden jedoch etwas weniger vertrauenswürdig, sobald Sie sich mit dem privaten Zustand einer anderen Klasse herumgetrieben haben.Bei Singleton geht es nicht um eine einzelne Instanz!
Im Gegensatz zu anderen Antworten möchte ich nicht darüber sprechen, was mit Singletons nicht stimmt, sondern Ihnen zeigen, wie mächtig und großartig sie sind, wenn sie richtig verwendet werden!
Lösung : Verwenden Sie einen Bootstrap-Prozess mit einem Thread, um alle Abhängigkeiten Ihres Singletons zu initialisieren.
Lösung : Verwenden Sie zum Verspotten die Methode Factory- Muster
Sie können
MyModel
einerTestMyModel
Klasse zuordnen , die es erbt. Überall, woMyModel
injiziert wird, werden SieTestMyModel
instread erhalten. - Problem : Singletons können Speicherlecks verursachen, da sie niemals entsorgt werden.Lösung : Nun, entsorgen Sie sie! Implementieren Sie einen Rückruf in Ihre App, um Singletons ordnungsgemäß zu entsorgen. Entfernen Sie alle damit verknüpften Daten und entfernen Sie sie schließlich aus der Factory.
Wie ich beim Titel sagte, handelt es sich bei Singleton nicht um eine einzelne Instanz.
quelle
Settings
Objekt, auf das von jedem Widget aus zugegriffen werden kann, damit jedes Widget weiß, wie angezeigte Zahlen formatiert werden. Wenn es kein global zugängliches Objekt wäre, müsste ich es im Konstruktor in jedes einzelne Widget im Konstruktor einfügen und den Verweis darauf als Mitgliedsvariable behalten. Dies ist eine schreckliche Verschwendung von Erinnerung und Zeit.Meine Antwort darauf, wie schlecht Singletons sind, lautet immer: "Sie sind schwer richtig zu machen". Viele der grundlegenden Komponenten von Sprachen sind Singletons (Klassen, Funktionen, Namespaces und sogar Operatoren), ebenso wie Komponenten in anderen Aspekten des Rechnens (localhost, Standardroute, virtuelles Dateisystem usw.), und dies ist kein Zufall. Während sie von Zeit zu Zeit Ärger und Frustration verursachen, können sie auch dazu führen, dass viele Dinge viel besser funktionieren.
Die zwei größten Probleme, die ich sehe, sind: Es wie ein globales Problem behandeln und den Singleton-Abschluss nicht definieren.
Alle reden von Singleton als Globalen, weil sie es im Grunde sind. Ein Großteil (leider nicht alle) der Schlechtigkeit in einem globalen Umfeld beruht jedoch nicht darauf, global zu sein, sondern darauf, wie Sie es verwenden. Gleiches gilt für Singletons. Umso mehr muss "Einzelinstanz" nicht unbedingt "global zugänglich" bedeuten. Es ist eher ein natürliches Nebenprodukt, und angesichts all des Schlechten, von dem wir wissen, dass es daraus resultiert, 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 bei jedem anderen Objekt dorthin navigieren. Der meiste Code sollte nicht einmal wissen, dass es sich um einen Singleton handelt (lose Kopplung, oder?). Wenn nur ein kleines Stück Code auf das Objekt zugreift, als wäre es ein globales Objekt, wird viel Schaden rückgängig gemacht.
Der Singleton-Kontext ist auch sehr wichtig. Das bestimmende Merkmal eines Singleton ist, dass es "nur einen" gibt, aber die Wahrheit ist, dass es "nur einen" innerhalb einer Art Kontext / Namespace gibt. Sie sind normalerweise eine von: eine pro Thread, Prozess, IP-Adresse oder Cluster, können aber auch eine pro Prozessor, Maschine, Sprachennamensraum / 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 einen gibt, heißt das nicht, dass ein Singleton allmächtig ist, "immer war und immer sein wird", und es ist auch im Allgemeinen nicht wünschenswert (Objekte ohne Anfang und Ende verletzen alle Arten nützlicher Annahmen im Code und sollten nur verwendet werden unter den verzweifeltsten Umständen.
Wenn Sie diese Fehler vermeiden, können Singletons immer noch eine PITA sein, aber es ist bereit zu sehen, dass viele der schlimmsten Probleme erheblich gemildert werden. Stellen Sie sich einen Java-Singleton vor, der explizit als einmal pro Klassenladeprogramm definiert ist (was bedeutet, dass eine Thread-Sicherheitsrichtlinie erforderlich ist), 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 Probleme.
Leider, anstatt gute Beispiele für Singletons zu vermitteln. Wir unterrichten schlechte Beispiele, lassen Programmierer eine Weile davonlaufen und sagen ihnen dann, dass es sich um ein schlechtes Entwurfsmuster handelt.
quelle
Siehe Wikipedia Singleton_pattern
Referenzen (nur relevante Referenzen aus dem Artikel)
quelle
Es ist nicht so, dass Singletons selbst schlecht sind, aber das GoF-Designmuster ist es. Das einzige wirklich gültige Argument ist, dass sich das GoF-Entwurfsmuster nicht für Tests eignet, insbesondere wenn Tests parallel ausgeführt werden.
Die Verwendung einer einzelnen Instanz einer Klasse ist ein gültiges Konstrukt, solange Sie die folgenden Mittel im Code anwenden:
Stellen Sie sicher, dass die Klasse, die als Singleton verwendet wird, eine Schnittstelle implementiert. Dadurch können Stubs oder Mocks über dieselbe Schnittstelle implementiert werden
Stellen Sie sicher, dass der Singleton threadsicher ist. Das ist eine gegebene.
Der Singleton sollte von Natur aus einfach und nicht übermäßig kompliziert sein.
Verwenden Sie zur Laufzeit Ihrer Anwendung, in der Singletons an ein bestimmtes Objekt übergeben werden müssen, eine Klassenfactory, die dieses Objekt erstellt, und lassen Sie die Klassenfactory die Singleton-Instanz an die Klasse übergeben, die sie benötigt.
Erstellen Sie während des Testens und um deterministisches Verhalten sicherzustellen, die Singleton-Klasse als separate Instanz, entweder als tatsächliche Klasse selbst oder als Stub / Mock, der ihr Verhalten implementiert, und übergeben Sie es unverändert an die Klasse, die es benötigt. Verwenden Sie nicht den Klassenfaktor, der das zu testende Objekt erstellt, das den Singleton während des Tests benötigt, da es die einzelne globale Instanz davon übergeben wird, wodurch der Zweck zunichte gemacht wird.
Wir haben Singletons in unseren Lösungen mit großem Erfolg verwendet, die testbar sind und deterministisches Verhalten in parallelen Testlaufströmen sicherstellen.
quelle
Ich möchte die 4 Punkte in der akzeptierten Antwort ansprechen, hoffentlich kann jemand erklären, warum ich falsch liege.
Warum ist es schlecht, Abhängigkeiten in Ihrem Code zu verbergen? Es gibt bereits Dutzende versteckter Abhängigkeiten (C-Laufzeitaufrufe, OS-API-Aufrufe, globale Funktionsaufrufe), und Singleton-Abhängigkeiten sind leicht zu finden (Suche zum Beispiel ()).
"Etwas global zu machen, um es nicht weiterzugeben, ist ein Code-Geruch." Warum wird nichts weitergegeben, um zu vermeiden, dass es als Singleton zu einem Code-Geruch wird?
Wenn Sie ein Objekt durch 10 Funktionen in einem Aufrufstapel übergeben, um einen Singleton zu vermeiden, ist das so großartig?
Prinzip der Einzelverantwortung: Ich denke, das ist etwas vage und hängt von Ihrer Definition der Verantwortung ab. Eine relevante Frage wäre, warum es wichtig ist, diese spezifische "Verantwortung" einer Klasse hinzuzufügen ?
Warum ist die Übergabe eines Objekts an eine Klasse enger gekoppelt als die Verwendung dieses Objekts als Singleton innerhalb der Klasse?
Warum ändert sich, wie lange der Staat dauert? Singletons können manuell erstellt oder zerstört werden, sodass das Steuerelement weiterhin vorhanden ist und Sie die Lebensdauer der Lebensdauer eines Nicht-Singleton-Objekts anpassen können.
In Bezug auf Unit-Tests:
quelle
Vince Huston hat diese Kriterien, die mir vernünftig erscheinen:
quelle
Singletons sind aus puristischer Sicht schlecht.
Aus praktischer Sicht ist ein Singleton ein Kompromiss zwischen Entwicklungszeit und Komplexität .
Wenn Sie wissen, dass sich Ihre Anwendung nicht so stark ändert, sind sie in Ordnung. Sie müssen nur wissen, dass Sie möglicherweise Änderungen vornehmen müssen, wenn sich Ihre Anforderungen auf unerwartete Weise ändern (was in den meisten Fällen ziemlich in Ordnung ist).
Singletons erschweren manchmal auch das Testen von Einheiten .
quelle
An dem Muster ist an sich nichts auszusetzen, vorausgesetzt, es wird für einen Aspekt Ihres Modells verwendet, der wirklich einzeln ist.
Ich glaube, das Spiel ist auf seine Überbeanspruchung zurückzuführen, was wiederum auf die Tatsache zurückzuführen ist, dass es das am einfachsten zu verstehende und zu implementierende Muster ist.
quelle
Ich werde das Gut / Böse-Argument nicht kommentieren, aber ich habe sie seit dem Frühling nicht mehr benutzt . Die Verwendung der Abhängigkeitsinjektion hat meine Anforderungen an Singleton, Servicelokalisierer und Fabriken so gut wie beseitigt. Ich finde dies eine viel produktivere und sauberere Umgebung, zumindest für die Art der Arbeit, die ich mache (Java-basierte Webanwendungen).
quelle
Singleton ist ein Muster und kann wie jedes andere Werkzeug verwendet oder missbraucht werden.
Der schlechte Teil eines Singletons ist im Allgemeinen der Benutzer (oder sollte ich die unangemessene Verwendung eines Singletons für Dinge sagen, für die er nicht entwickelt wurde). Der größte Täter verwendet einen Singleton als gefälschte globale Variable.
quelle
Wenn Sie Code mit Singletons schreiben, z. B. einem Logger oder einer Datenbankverbindung, und anschließend feststellen, dass Sie mehr als ein Protokoll oder mehr als eine Datenbank benötigen, sind Sie in Schwierigkeiten.
Singletons machen es sehr schwer, sich von ihnen zu normalen Objekten zu bewegen.
Außerdem ist es zu einfach, einen nicht threadsicheren Singleton zu schreiben.
Anstatt Singletons zu verwenden, sollten Sie alle erforderlichen Dienstprogrammobjekte von Funktion zu Funktion übergeben. Das kann vereinfacht werden, wenn Sie alle wie folgt in ein Hilfsobjekt einwickeln:
quelle
Das Problem mit Singletons ist das Problem des größeren Umfangs und damit der Kopplung . Es ist nicht zu leugnen, dass es einige Situationen gibt, in denen Sie Zugriff auf eine einzelne Instanz benötigen, und dies kann auf andere Weise erreicht werden.
Ich ziehe es jetzt vor, einen IoC-Container ( Inversion of Control ) zu entwerfen und zuzulassen, dass die Lebensdauern vom Container gesteuert werden. Dies gibt Ihnen den Vorteil, dass die von der Instanz abhängigen Klassen nicht wissen, dass es eine einzelne Instanz gibt. Die Lebensdauer des Singletons kann in Zukunft geändert werden. Ein solches Beispiel, auf das ich kürzlich gestoßen bin, war eine einfache Anpassung von Single-Threaded zu Multi-Threaded.
FWIW, wenn es sich um eine PIA handelt, wenn Sie versuchen, sie einem Unit-Test zu unterziehen, wird sie an PIA weitergeleitet, wenn Sie versuchen, sie zu debuggen, Fehler zu beheben oder zu verbessern.
quelle
Aktueller Artikel zu diesem Thema von Chris Reath bei Coding Without Comments .
Hinweis: Codierung ohne Kommentare ist nicht mehr gültig. Der Artikel, mit dem verlinkt wird, wurde jedoch von einem anderen Benutzer geklont.
http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx
quelle
Singletons sind NICHT schlecht. Es ist nur schlecht, wenn Sie etwas global Einzigartiges machen, das nicht global einzigartig ist.
Es gibt jedoch "Application Scope Services" (denken Sie an ein Messaging-System, mit dem Komponenten interagieren) - diese CALLS für einen Singleton, eine "MessageQueue" -Klasse mit der Methode "SendMessage (...)".
Sie können dann von überall aus Folgendes tun:
MessageQueue.Current.SendMessage (neue MailArrivedMessage (...));
Und natürlich:
MessageQueue.Current.RegisterReceiver (this);
in Klassen, die IMessageReceiver implementieren.
quelle
Zu viele Leute fügen Objekte, die nicht threadsicher sind, in ein Singleton-Muster ein. Ich habe Beispiele für einen DataContext ( LINQ to SQL ) gesehen, der in einem Singleton-Muster erstellt wurde, obwohl der DataContext nicht threadsicher und lediglich ein Arbeitseinheitsobjekt ist.
quelle
Hier ist noch eine Sache über Singletons, die noch niemand gesagt hat.
In den meisten Fällen ist "Singletonity" eher ein Detail der Implementierung für eine Klasse als ein Merkmal ihrer Schnittstelle. Die Inversion des Steuercontainers kann dieses Merkmal vor Klassenbenutzern verbergen. Sie müssen Ihre Klasse nur als Singleton markieren (
@Singleton
z. B. mit Anmerkungen in Java) und fertig. IoCC erledigt den Rest. Sie müssen keinen globalen Zugriff auf Ihre Singleton-Instanz bereitstellen, da der Zugriff bereits von IoCC verwaltet wird. Somit ist an IoC Singletons nichts auszusetzen.GoF-Singletons im Gegensatz zu IoC-Singletons sollen "Singletonity" in der Schnittstelle durch die Methode getInstance () verfügbar machen, damit sie unter allem leiden, was oben gesagt wurde.
quelle
Singletons sind nicht böse, wenn Sie sie richtig und minimal verwenden . Es gibt viele andere gute Designmuster, die irgendwann die Anforderungen von Singleton ersetzen (und auch die besten Ergebnisse liefern). Aber einige Programmierer sind sich dieser guten Muster nicht bewusst und verwenden den Singleton für alle Fälle, was den Singleton für sie böse macht.
quelle
Erstens sollten eine Klasse und ihre Mitarbeiter zunächst ihren beabsichtigten Zweck erfüllen, anstatt sich auf abhängige Personen zu konzentrieren. Das Lebenszyklusmanagement (wenn Instanzen erstellt werden und wenn sie außerhalb des Gültigkeitsbereichs liegen) sollte nicht Teil der Klassenverantwortung sein. Die bewährte Vorgehensweise hierfür besteht darin, eine neue Komponente zu erstellen oder zu konfigurieren, um Abhängigkeiten mithilfe der Abhängigkeitsinjektion zu verwalten.
Oft wird Software komplizierter. Es ist sinnvoll, mehrere unabhängige Instanzen der Singleton-Klasse mit unterschiedlichem Status zu haben. In solchen Fällen ist es falsch, Code festzulegen, um einfach den Singleton zu greifen. Die Verwendung
Singleton.getInstance()
mag für kleine einfache Systeme in Ordnung sein, funktioniert jedoch nicht / skaliert nicht, wenn eine andere Instanz derselben Klasse benötigt wird.Keine Klasse sollte als Singleton betrachtet werden, sondern sollte eine Anwendung ihrer Verwendung oder der Art und Weise sein, wie sie zum Konfigurieren von abhängigen Personen verwendet wird. Für eine schnelle und unangenehme Angelegenheit spielt dies keine Rolle - nur eine lauharte Codierung sagt, dass Dateipfade keine Rolle spielen, aber für größere Anwendungen müssen solche Abhängigkeiten mit DI herausgerechnet und in geeigneterer Weise verwaltet werden.
Die Probleme, die Singleton beim Testen verursacht, sind ein Symptom für den fest codierten Einzelanwendungsfall / die Umgebung. Die Testsuite und die vielen Tests sind jeweils einzeln und trennen etwas, das nicht mit der harten Codierung eines Singletons kompatibel ist.
quelle
Da es sich im Grunde genommen um objektorientierte globale Variablen handelt, können Sie Ihre Klassen normalerweise so gestalten, dass Sie sie nicht benötigen.
quelle