Seien wir ehrlich. Das Singleton-Muster ist ein sehr kontroverses Thema mit Hordenprogrammierern auf beiden Seiten des Zauns. Es gibt Menschen, die das Gefühl haben, der Singleton sei nichts anderes als eine verherrlichte globale Variable, und andere, die auf Muster schwören und es ununterbrochen verwenden. Ich möchte jedoch nicht, dass die Singleton-Kontroverse im Mittelpunkt meiner Frage steht. Jeder kann ein Tauziehen haben und es bekämpfen und sehen, wer für alles gewinnt, was mir wichtig ist . Ich versuche zu sagen, ich glaube nicht, dass es eine einzige richtige Antwort gibt, und ich versuche nicht absichtlich, Partisanenstreitigkeiten zu entfachen. Ich interessiere mich einfach für Singleton-Alternativen, wenn ich die Frage stelle:
Gibt es spezielle Alternativen zum GOF Singleton Pattern?
Wenn ich beispielsweise in der Vergangenheit oft das Singleton-Muster verwendet habe, bin ich einfach daran interessiert, den Status / die Werte einer oder mehrerer Variablen beizubehalten. Der Zustand / die Werte von Variablen können jedoch zwischen jeder Instanziierung der Klasse unter Verwendung statischer Variablen anstelle des Singleton-Musters beibehalten werden .
Welche andere Idee hast du?
EDIT: Ich möchte nicht, dass dies ein weiterer Beitrag über "Wie man den Singleton richtig benutzt" ist. Wieder suche ich nach Möglichkeiten, dies zu vermeiden. Zum Spaß, ok? Ich schätze, ich stelle eine rein akademische Frage in Ihrer besten Filmtrailer-Stimme: "Was können wir in einem Paralleluniversum tun, in dem es keinen Singleton gibt?"
quelle
Antworten:
Alex Miller zitiert in " Patterns I Hate " Folgendes:
"Wenn ein Singleton die Antwort zu sein scheint, finde ich es oft klüger:
quelle
Um zu verstehen, wie Singletons richtig umgangen werden können, müssen Sie verstehen, was mit Singletons (und dem globalen Status im Allgemeinen) nicht stimmt:
Singletons verbergen Abhängigkeiten.
Warum ist das wichtig?
Denn wenn Sie die Abhängigkeiten ausblenden, verlieren Sie häufig den Überblick über das Ausmaß der Kopplung.
Sie könnten das argumentieren
ist einfacher als
Aber zumindest die zweite API macht deutlich, was genau die Mitarbeiter der Methode sind.
Die Umgehung von Singletons besteht also nicht darin, statische Variablen oder Service-Locators zu verwenden, sondern die Singleton-Klassen in Instanzen zu ändern, die in dem Bereich instanziiert werden, in dem sie sinnvoll sind, und in die Komponenten und Methoden eingefügt werden, die sie benötigen. Sie können ein IoC-Framework verwenden, um dies zu handhaben, oder Sie können es manuell tun, aber das Wichtigste ist, Ihren globalen Status loszuwerden und die Abhängigkeiten und Kollaborationen explizit zu machen.
quelle
Die beste Lösung, auf die ich gestoßen bin, ist die Verwendung des Factory-Musters, um Instanzen Ihrer Klassen zu erstellen. Mithilfe des Musters können Sie sicherstellen, dass nur eine Instanz einer Klasse von den Objekten gemeinsam genutzt wird, die sie verwenden.
Ich dachte, es wäre kompliziert zu verwalten, aber nach dem Lesen dieses Blog-Beitrags "Wo sind all die Singletons geblieben?" scheint es so natürlich. Abgesehen davon hilft es sehr bei der Isolierung Ihrer Unit-Tests.
Was müssen Sie zusammenfassend tun? Wenn ein Objekt von einem anderen abhängt, erhält es eine Instanz nur über seinen Konstruktor (kein neues Schlüsselwort in Ihrer Klasse).
Und dann die Fabrik.
Da Sie Ihre Factory nur einmal instanziieren, wird exSingleton nur einmal instanziiert. Jedes Mal, wenn Sie buildNeedy aufrufen, wird die neue Instanz von NeedyClass mit exSingleton gebündelt.
Ich hoffe das hilft. Bitte weisen Sie auf Fehler hin.
quelle
Spring oder irgendein anderer IoC-Container leistet dabei einigermaßen gute Arbeit. Da die Klassen außerhalb der App selbst erstellt und verwaltet werden, kann der Container einfache Klassen-Singletons erstellen und bei Bedarf einfügen.
quelle
Sie sollten nicht aus dem Weg gehen müssen, um Muster zu vermeiden. Die Verwendung eines Musters ist entweder eine Entwurfsentscheidung oder eine natürliche Anpassung (es passt einfach zusammen). Wenn Sie ein System entwerfen, haben Sie die Wahl, entweder ein Muster zu verwenden oder das Muster nicht zu verwenden. Sie sollten sich jedoch nicht die Mühe machen, alles zu vermeiden, was letztendlich eine Designentscheidung ist.
Ich vermeide das Singleton-Muster nicht. Entweder ist es angemessen und ich benutze es oder es ist nicht angemessen und ich benutze es nicht. Ich glaube, dass es so einfach ist.
Die Angemessenheit (oder das Fehlen davon) des Singleton hängt von der Situation ab. Es ist eine Entwurfsentscheidung, die getroffen werden muss, und die Konsequenzen dieser Entscheidung müssen verstanden (und dokumentiert) werden.
quelle
Monostate (beschrieben in Robert C. Martins Agile Software Development) ist eine Alternative zu Singleton. In diesem Muster sind die Daten der Klasse alle statisch, aber die Getter / Setter sind nicht statisch.
Beispielsweise:
Monostate verhält sich ähnlich wie Singleton, jedoch so, dass der Programmierer nicht unbedingt weiß, dass ein Singleton verwendet wird.
quelle
Das Singleton- Muster existiert, weil es Situationen gibt, in denen ein einzelnes Objekt benötigt wird, um eine Reihe von Diensten bereitzustellen .
Selbst wenn dies der Fall ist, halte ich den Ansatz, Singletons mithilfe eines globalen statischen Felds / einer globalen statischen Eigenschaft, die die Instanz darstellt, zu erstellen , für unangemessen. Dies ist unangemessen, da im Code eine Abhängigkeit zwischen dem statischen Feld und dem Objekt entsteht, nicht zwischen den Diensten, die das Objekt bereitstellt.
Anstelle des klassischen Singleton-Musters empfehle ich daher, das Service-Like-Muster für Serviced Container zu verwenden. Wenn Sie Ihren Singleton nicht über ein statisches Feld verwenden, erhalten Sie einen Verweis darauf über eine Methode, die den erforderlichen Servicetyp anfordert.
statt einzeln global
Auf diese Weise haben Sie es leicht, wenn Sie den Typ eines Objekts von Singleton in etwas anderes ändern möchten. Als zusätzlichen Vorteil müssen Sie nicht alle Objektinstanzen an jede Methode weitergeben.
Siehe auch Inversion of Control . Die Idee ist, dass Sie durch direktes Aussetzen von Singletons für den Verbraucher eine Abhängigkeit zwischen dem Verbraucher und der Objektinstanz erstellen, nicht zwischen den vom Objekt bereitgestellten Objektdiensten.
Meine Meinung ist, die Verwendung des Singleton-Musters nach Möglichkeit zu verbergen , da es nicht immer möglich oder wünschenswert ist, es zu vermeiden.
quelle
Wenn Sie einen Singleton zur Darstellung eines einzelnen Datenobjekts verwenden, können Sie stattdessen ein Datenobjekt als Methodenparameter übergeben.
(obwohl ich behaupten würde, dass dies der falsche Weg ist, einen Singleton überhaupt zu verwenden)
quelle
Wenn Ihr Problem darin besteht, dass Sie den Status beibehalten möchten, möchten Sie eine MumbleManager-Klasse. Bevor Sie mit einem System arbeiten, erstellt Ihr Client einen MumbleManager, wobei Mumble der Name des Systems ist. Der Staat bleibt dadurch erhalten. Möglicherweise enthält Ihr MumbleManager eine Eigenschaftstasche, die Ihren Status enthält.
Diese Art von Stil fühlt sich sehr C-artig und nicht sehr objektartig an - Sie werden feststellen, dass Objekte, die Ihr System definieren, alle einen Verweis auf denselben MumbleManager haben.
quelle
Verwenden Sie ein einfaches Objekt und ein Factory-Objekt. Die Fabrik ist dafür verantwortlich, die Instanz und die einfachen Objektdetails nur mit den Konfigurationsinformationen (die sie beispielsweise enthält) und dem Verhalten zu überwachen.
quelle
Wenn Sie beim Vermeiden von Singeltons von Grund auf neu entwerfen, müssen Sie möglicherweise nicht umgehen, indem Sie Singletons nicht mithilfe statischer Variablen verwenden. Wenn Sie statische Variablen verwenden, erstellen Sie auch mehr oder weniger einen Singleton. Der einzige Unterschied besteht darin, dass Sie verschiedene Objektinstanzen erstellen. Intern verhalten sich jedoch alle so, als würden sie einen Singleton verwenden.
Können Sie vielleicht ein detailliertes Beispiel geben, wo Sie einen Singleton verwenden oder wo derzeit ein Singleton verwendet wird und Sie versuchen, die Verwendung zu vermeiden? Dies könnte den Menschen helfen, eine ausgefallenere Lösung zu finden, wie die Situation ohne einen Singleton überhaupt gehandhabt werden könnte.
Übrigens habe ich persönlich keine Probleme mit Singletons und ich kann die Probleme, die andere Leute in Bezug auf Singletons haben, nicht verstehen. Ich sehe nichts schlechtes an ihnen. Das heißt, wenn Sie sie nicht missbrauchen. Jede nützliche Technik kann missbraucht werden und wenn sie missbraucht wird, führt dies zu negativen Ergebnissen. Eine andere Technik, die häufig missbraucht wird, ist die Vererbung. Trotzdem würde niemand sagen, dass Vererbung etwas Schlimmes ist, nur weil manche Leute es schrecklich missbrauchen.
quelle
Persönlich ist für mich eine viel sinnvollere Möglichkeit, etwas zu implementieren, das sich wie Singleton verhält, die Verwendung einer vollständig statischen Klasse (statische Elemente, statische Methoden, statische Eigenschaften). Die meiste Zeit implementiere ich es auf diese Weise (ich kann mir keine Verhaltensunterschiede aus Anwendersicht vorstellen)
quelle
Ich denke, der beste Ort, um den Singleton zu überwachen, ist das Design der Klasse. Zu diesem Zeitpunkt sollten Sie in der Lage sein, die Interaktionen zwischen Klassen abzubilden und festzustellen, ob etwas absolut erforderlich ist, dass zu jedem Zeitpunkt des Anwendungslebens nur eine Instanz dieser Klasse vorhanden ist.
Wenn dies der Fall ist, haben Sie einen Singleton. Wenn Sie Singletons als Annehmlichkeit beim Codieren einwerfen, sollten Sie Ihr Design wirklich überdenken und auch aufhören, diese Singletons zu codieren :)
Und ja, "Polizei" ist das Wort, das ich hier meinte, anstatt "zu vermeiden". Der Singleton ist nicht zu vermeiden (genauso wie goto und globale Variablen nicht zu vermeiden sind). Stattdessen sollten Sie die Verwendung überwachen und sicherstellen, dass dies die beste Methode ist, um das, was Sie möchten, effektiv zu erledigen.
quelle
Ich benutze Singleton meistens als "Methodencontainer", ohne Status. Wenn ich diese Methoden mit vielen Klassen teilen muss und die Last der Instanziierung und Initialisierung vermeiden möchte, erstelle ich einen Kontext / eine Sitzung und initialisiere alle Klassen dort. Alles, was sich auf die Sitzung bezieht, hat auch Zugriff auf den darin enthaltenen "Singleton".
quelle
Da ich nicht in einer stark objektorientierten Umgebung (z. B. Java) programmiert habe, bin ich nicht ganz über die Feinheiten der Diskussion informiert. Aber ich habe ein Singleton in PHP 4 implementiert. Ich habe es getan, um einen 'Black-Box'-Datenbankhandler zu erstellen, der automatisch initialisiert wurde und nicht in einem unvollständigen und etwas kaputten Framework an Funktionsaufrufe weitergeleitet werden musste.
Nachdem ich einige Links von Singleton-Mustern gelesen habe, bin ich mir nicht ganz sicher, ob ich es wieder auf die gleiche Weise implementieren würde. Was wirklich benötigt wurde, waren mehrere Objekte mit gemeinsam genutztem Speicher (z. B. das eigentliche Datenbankhandle), und genau das wurde aus meinem Aufruf.
Wie bei den meisten Mustern und Algorithmen ist die Verwendung eines Singletons "nur weil es cool ist" The Wrong Thing To Do. Ich brauchte einen echten Black-Box-Anruf, der einem Singleton sehr ähnlich sah. Und IMO ist der Weg, um die Frage anzugehen: Seien Sie sich des Musters bewusst, aber schauen Sie sich auch den weiteren Umfang an und auf welcher Ebene die Instanz eindeutig sein muss.
quelle
Was meinst du, was sind meine Techniken, um es zu vermeiden?
Um dies zu "vermeiden", bedeutet dies, dass es viele Situationen gibt, in denen das Singleton-Muster von Natur aus gut passt, und dass ich daher einige Maßnahmen ergreifen muss, um diese Situationen zu entschärfen.
Aber es gibt keine. Ich muss das Singleton-Muster nicht vermeiden. Es entsteht einfach nicht.
quelle