Frage Was ist so schlimm an Singles? [geschlossen]


Das Singleton-Muster ist ein voll bezahltes Mitglied der GoFist es Musterbuch, aber es scheint in letzter Zeit ziemlich verwaist von der Entwicklerwelt. Ich benutze immer noch ziemlich viele Singletons, besonders für Fabrikklassenund obwohl man bei Multithreading-Problemen (wie jeder Klasse) vorsichtig sein muss, kann ich nicht verstehen, warum sie so schrecklich sind.

Besonders scheint Stack Overflow davon auszugehen, dass alle zustimmen, dass Singletons böse sind. Warum?

Bitte unterstütze deine Antworten mit "Fakten, Referenzen oder spezifische Expertise"


1737


Ursprung


Antworten:


Von Brian Button paraphrasiert:

  1. 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 Globales zu machen, um es nicht herumzureichen, ist a Code riechen.

  2. Sie verletzen die Grundsatz der einheitlichen Verantwortung: aufgrund der Tatsache, dass sie ihre eigene Schöpfung und ihren Lebenszyklus kontrollieren.

  3. Sie verursachen von Natur aus einen engen Code gekoppelt. Dies macht es in vielen Fällen schwierig, sie im Test zu fälschen.

  4. Sie tragen den Status für die Lebensdauer der Anwendung. Ein weiterer Erfolg beim Testen, da Sie mit einer Situation konfrontiert werden, in der Tests bestellt werden müssen, was ein großes Nein für Komponententests ist. Warum? Weil jeder Komponententest unabhängig von dem anderen sein sollte.


1148



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

Ressourcenkonflikt

Wenn Sie eine Ressource haben

(1) kann nur eine einzige Instanz haben, und

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

du brauchst ein Singleton.

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

Es ist selten, dass du ein Singleton brauchst. Der Grund, warum sie schlecht sind, ist, dass sie sich anfühlen global und sie sind ein voll bezahltes Mitglied der GoF Designmuster Buch.

Wenn Sie denken, dass Sie ein globales brauchen, machen Sie wahrscheinlich einen schrecklichen Designfehler.


399



Einige Coding Snobs sehen auf sie als nur eine verklärte globale herab. So wie viele Menschen das hassen gehe zu Aussage gibt es andere, die die Idee hassen, jemals ein global. Ich habe mehrere Entwickler gesehen, die außergewöhnlich viel unternommen haben, um ein zu vermeiden global weil sie in Betracht zogen, einen als Eingeständnis des Scheiterns zu benutzen. Komisch aber wahr.

In der Praxis Singleton Muster ist nur eine Programmiertechnik, die ein nützlicher Teil Ihres Toolkits von Konzepten ist. Von Zeit zu Zeit finden Sie vielleicht die ideale Lösung und nutzen Sie sie. Aber benutze es nur, damit du dich rühmen kannst, ein Design-Muster ist genauso dumm wie sich weigert, es jemals zu benutzen, weil es nur eine ist global.


306



Misko Hevery, von Google, hat einige interessante Artikel zu genau diesem Thema ...

Singletons sind pathologische Lügner hat ein Unit-Testing-Beispiel, das veranschaulicht, wie Singletons die Ermittlung von Abhängigkeitsketten erschweren und eine Anwendung starten oder testen können. Es ist ein ziemlich extremes Beispiel für Missbrauch, aber der Punkt, den er macht, ist immer noch gültig:

Singletons sind nichts anderes als ein globaler Staat. Der globale Status sorgt dafür, dass deine Objekte heimlich Dinge erreichen können, die nicht in ihren APIs deklariert sind, und Singles machen aus deinen APIs pathologische Lügner.

Wo sind alle Singletons gegangen? macht den Punkt, dass die Abhängigkeitsinjektion es leicht gemacht hat, Instanzen zu Konstruktoren zu bringen, die sie benötigen, was die zugrunde liegende Notwendigkeit hinter den schlechten, globalen Singletons, die im ersten Artikel verschrien sind, verringert.


200



Ich denke, dass die Verwirrung durch die Tatsache verursacht wird, dass die Leute die tatsächliche Anwendung des Singleton-Musters nicht kennen. Ich kann das nicht genug betonen. Singleton ist nicht ein Muster zum Umhüllen von Globalen. Singleton-Muster sollten nur verwendet werden, um dies zu garantieren eine und nur eine Instanz einer bestimmten Klasse existiert während der Laufzeit.

Leute denken Singleton ist böse, weil sie es für Globals verwenden. Wegen dieser Verwirrung wird Singleton herabgewürdigt. Bitte verwirren Sie Singletons und Globals nicht. Wenn Sie es für den Zweck verwenden, für den es bestimmt war, werden Sie extreme Vorteile aus dem Singleton-Muster ziehen.


103



Eine ziemlich schlechte Sache über Singletons ist, dass Sie sie nicht sehr einfach erweitern können. Sie müssen im Grunde eine Art von bauen Dekorationsmuster oder so etwas, wenn Sie ihr Verhalten ändern wollen. Wenn Sie eines Tages mehrere Möglichkeiten haben wollen, diese eine Sache zu tun, kann es ziemlich schmerzhaft sein, sich zu ändern, je nachdem, wie Sie Ihren Code gestalten.

Eine Sache zu beachten, wenn Sie Singletons verwenden, versuchen, sie an diejenigen weitergeben, die sie braucht, anstatt sie direkt zugreifen müssen ... Andernfalls, wenn Sie sich entscheiden, mehrere Möglichkeiten haben, die Sache, die Singleton tut, wird es sein eher schwierig zu ändern, da jede Klasse eine Abhängigkeit einbettet, wenn sie direkt auf den Singleton zugreift.

Also im Grunde genommen:

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

eher, als:

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

Ich glaube, diese Art von Muster wird genannt Abhängigkeitsspritze und wird allgemein als eine gute Sache angesehen.

Wie jedes Muster ... Denken Sie darüber nach und überlegen Sie, ob seine Verwendung in der gegebenen Situation unangemessen ist oder nicht ... Regeln werden normalerweise gebrochen, und Muster sollte nilly nilly ohne nachdenken nicht angewendet werden.


71



Das Singleton-Muster ist an sich kein Problem. Das Problem ist, dass das Muster oft von Leuten benutzt wird, die Software mit objektorientierten Werkzeugen entwickeln, ohne ein solides Verständnis von OO-Konzepten zu haben. Wenn Singletons in diesem Zusammenhang eingeführt werden, tendieren sie dazu, zu nicht handhabbaren Klassen zu wachsen, die Hilfsmethoden für jede kleine Verwendung enthalten.

Singletons sind auch ein Testproblem. Sie neigen dazu, isolierte Komponententests schwierig zu schreiben. Inversion der Kontrolle (IoC) und Abhängigkeitsspritze sind Muster, die dazu gedacht sind, dieses Problem objektorientiert zu lösen, das sich für Unit-Tests eignet.

In einem Müll gesammelt Environment Singletons können schnell zu einem Problem hinsichtlich der Speicherverwaltung werden.

Es gibt auch das Multithread-Szenario, bei dem Singletons sowohl zu einem Engpass als auch zu einem Synchronisationsproblem werden können.


65



Ein Singleton wird mit einer statischen Methode implementiert. Statische Methoden werden von Leuten vermieden, die Komponententests durchführen, weil sie nicht verspottet oder gestempelt werden können. Die meisten Leute auf dieser Seite sind große Befürworter von Komponententests. Die allgemein akzeptierte Konvention, um sie zu vermeiden, benutzt die Inversion der Kontrolle Muster.


52



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

Berücksichtigen Sie die folgende Situation: Als Entwickler müssen Sie eine Webanwendung erstellen, die auf eine Datenbank zugreift. Um sicherzustellen, dass sich gleichzeitige Datenbankaufrufe nicht gegenseitig stören, erstellen Sie eine Thread-Sicherung SingletonDao:

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

Sie sind also sicher, dass nur ein Singleton in Ihrer Anwendung vorhanden ist und alle Datenbanken diese nur durchlaufen SingletonDao. Ihre Produktionsumgebung sieht nun so aus: Single Singleton

Alles ist soweit in Ordnung.

Betrachten Sie nun, dass Sie mehrere Instanzen Ihrer Webanwendung in einem Cluster einrichten möchten. Jetzt hast du plötzlich so etwas:

Many singletons

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 vornehmen möchten.

Natürlich ist dies ein Beispiel für eine schlechte Verwendung eines Singleton. Aber die Botschaft dieses Beispiels ist: Sie können sich nicht darauf verlassen, dass es in Ihrer Anwendung genau eine Instanz eines Singletons gibt - insbesondere wenn es um Clustering geht.


42



  1. Es wird leicht (ab) als globale Variable verwendet.
  2. Klassen, die auf Singletons angewiesen sind, sind relativ viel schwieriger isoliert zu testen.

34



Monopoly ist der Teufel und Singletons mit nicht-readonly / veränderbarem Zustand sind das "echte" Problem ...

Nach dem Lesen Singletons sind pathologische Lügner wie in. vorgeschlagen Jasons Antwort Ich bin auf diesen kleinen Leckerbissen gestoßen, der das am besten präsentierte Beispiel darstellt Wie Singletons werden oft missbraucht.

Global ist schlecht, weil:

  • ein. Es verursacht Namespace-Konflikt
  • b. Es entlarvt den Staat in einer ungerechtfertigten Weise

Wenn es um Singletons geht

  • ein. Die explizite OO-Art, sie aufzurufen, verhindert die Konflikte, also zeige a. ist kein Problem
  • b. Singletons ohne Staat sind (wie Fabriken) kein Problem. Singletons mit Zustand können wieder in zwei Kategorien fallen, die unveränderlich sind oder einmal schreiben und viele lesen (config / property files). Das sind nicht schlecht. Mutable Singletons, die Art von Referenzhaltern sind diejenigen, von denen Sie sprechen.

In der letzten Aussage bezieht er sich auf das Konzept des Blogs "Singletons sind Lügner".

Wie sieht das für Monopoly aus?

Um ein Spiel des Monopols zu beginnen, zuerst:

  • Wir legen zuerst die Regeln fest, damit alle auf der gleichen Seite sind
  • Jeder hat zu Beginn des Spiels einen gleichberechtigten Start
  • Zur Vermeidung von Verwechslungen wird nur ein Satz von Regeln vorgestellt
  • Die Regeln dürfen sich während des Spiels nicht ändern

Nun, für jeden, der das nicht getan hat Ja wirklich Monopol, diese Standards sind bestenfalls ideal. Eine Niederlage im Monopol ist schwer zu schlucken, weil Monopol über Geld geht. Wenn du verlierst, musst du genau beobachten, wie die anderen Spieler das Spiel beenden, und Verluste sind normalerweise schnell und erdrückend. Also werden die Regeln in der Regel irgendwann verdreht, um den Eigeninteressen einiger Spieler auf Kosten der anderen zu dienen.

Sie spielen also Monopoly mit Freunden Bob, Joe und Ed. Sie bauen schnell Ihr Imperium auf und konsumieren Marktanteile mit einer exponentiellen Rate. Ihre Gegner werden schwächer und Sie beginnen Blut zu riechen (bildlich). Dein Kumpel Bob hat sein gesamtes Geld in so viele Objekte wie möglich gesteckt, aber er bekommt keine hohe Rendite, so wie er es erwartet hat. Bob landet als Pech auf deinem Boardwalk und wird aus dem Spiel entfernt.

Jetzt geht das Spiel von freundlichen Würfelwürfen zu ernsthaften Geschäften. Bob wurde zum Beispiel des Versagens gemacht und Joe und Ed wollen nicht wie 'dieser Typ' enden. So werden Sie auf einmal der führende Spieler, der zum Feind wird. Joe und Ed beginnen mit Under-the-Table-Trades, hinter den Rücken liegenden Geldspritzen, unterbewertetem Haustausch und generell allem, was dich als Spieler schwächt, bis einer von ihnen an die Spitze kommt.

Dann, statt dass einer von ihnen gewinnt, beginnt der Prozess von vorne. Plötzlich wird eine endliche Reihe von Regeln zu einem beweglichen Ziel und das Spiel degeneriert in die Art von sozialen Interaktionen, die die Grundlage jeder hoch bewerteten Reality-TV-Show seit Survivor bilden würden. Warum, weil sich die Regeln ändern und es keinen Konsens darüber gibt, wie / warum / was sie darstellen sollen, und noch wichtiger, es gibt niemanden, der die Entscheidungen trifft. Jeder Spieler im Spiel macht dann seine eigenen Regeln und Chaos entsteht, bis zwei der Spieler zu müde sind, um die Farce aufrecht zu erhalten und langsam aufzugeben.

Wenn also ein Regelwerk für ein Spiel genau einen Singleton darstellt, wäre das Monopol-Regelwerk ein Beispiel für Missbrauch.

Wie sieht das für die Programmierung aus?

Abgesehen von all den offensichtlichen Threadsicherheits- und Synchronisationsproblemen, die veränderbare Singletons darstellen ... Wenn Sie einen Datensatz haben, der gleichzeitig von mehreren verschiedenen Quellen gelesen / manipuliert werden kann und während der Laufzeit der Anwendungsausführung existiert, Es ist wahrscheinlich ein guter Zeitpunkt, 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 der ganzen Threads, die benötigt wurden, um ihn threadsicher zu machen) und ein Albtraum war, an dem gearbeitet werden konnte (wegen der unvorhersehbaren / intermittierenden Synchronisationsfehler) fast unmöglich, unter "Produktionsbedingungen" zu testen. Sicher, ein System könnte mit Polling / Signaling entwickelt worden sein, um einige der Performance-Probleme zu überwinden, aber das würde die Probleme beim Testen nicht lösen und warum sich die Mühe machen, wenn eine 'echte' Datenbank die gleiche Funktionalität schon viel robuster ausführen kann / skalierbare Art und Weise.

Ein Singleton ist nur eine Option, wenn Sie brauchen, was ein Singleton bietet. Eine schreibgeschützte Nur-Lese-Instanz eines Objekts. Diese Regel sollte auch auf die Eigenschaften / Elemente des Objekts angewendet werden.


30