Frage

Die verherrlichte globale Variable - wird zu einer gloried globalen Klasse. Einige sagen, Bruchobjektorientiertes Design.

Geben Sie mir Szenarien, andere als den guten alten Logger, wo es Sinn macht, die Singleton zu verwenden.

War es hilfreich?

Lösung

Auf meiner Suche nach der Wahrheit entdeckte ich, dass es tatsächlich nur sehr wenige „akzeptabel“ Gründe sind ein Singleton zu verwenden.

Ein Grund, der auf dem Internets immer und immer wieder kommen zumeist an einer „logging“ Klasse (die Sie erwähnen). In diesem Fall kann ein Singleton anstelle einer einzelnen Instanz einer Klasse verwendet werden, da eine Logging-Klasse in die Regel werden muss, immer und immer wieder zum Überdruss von jeder Klasse in einem Projekt. Wenn jede Klasse diese Protokollierung-Klasse verwendet, Dependency Injection wird umständlich.

Die Protokollierung ist ein konkretes Beispiel für einen „akzeptabel“ Singleton, weil es nicht die Ausführung des Codes nicht beeinträchtigt. Deaktivieren Sie die Protokollierung, die Codeausführung bleibt gleich. Aktivieren Sie es, same same. Misko bringt es auf folgende Weise in Root Cause von Singletons „die hier aufgeführten Informationen fließen eine Art und Weise: in der Anwendung in den Logger obwohl Logger globaler Zustand ist, da keine Informationen von Loggern in Ihre Anwendung fließt, Logger akzeptabel ist..“

Ich bin sicher, es gibt andere auch gute Gründe. Alex Miller, in " Patterns I Hate ", spricht von Service-Locators und Client-Seite UI ist möglicherweise auch als "akzeptabel" Entscheidungen zu sein.

Lesen Sie mehr bei Singleton ich liebe dich, aber Sie bringen mich.

Andere Tipps

Ein Singleton Kandidat muss drei Voraussetzungen erfüllen:

  • steuert den gleichzeitigen Zugriff auf eine gemeinsam genutzte Ressource.
  • Zugriff auf die Ressource wird von mehreren, unterschiedlichen Teilen des Systems angefordert werden.
  • Es kann nur ein Objekt sein.

Wenn Ihr Vorschlag Singleton nur ein oder zwei dieser Anforderungen hat, ist ein Redesign fast immer die richtige Wahl.

Zum Beispiel kann ein Drucker-Spooler ist unwahrscheinlich, dass aus mehr als ein Ort (das Druckmenü) aufgerufen werden, so können Sie Mutexe verwenden, um das gleichzeitige Zugriffsproblem zu lösen.

Eine einfache Logger ist das offensichtlichste Beispiel für eine möglicherweise gültige Singleton, aber dies kann mit komplexeren Logging-Systemen ändern.

Beim Lesen Konfigurationsdateien, die nur beim Start gelesen werden sollen und sie in einem Singleton eingekapselt wird.

Sie verwenden einen Singleton, wenn Sie eine gemeinsam genutzte Ressource verwalten müssen. Zum Beispiel kann ein Drucker-Spooler. Ihre Anwendung sollte nur eine einzige Instanz des Spooler, um widersprüchliche Anforderung für die gleiche Ressource zu vermeiden.

oder eine Datenbankverbindung oder ein Dateimanager etc.

Lesen Sie nur Singletons einige globalen Zustand Speichern (Benutzersprache, helfen filepath, Anwendungspfad) sind angemessen. Seien Sie vorsichtig von Singletons mit Geschäftslogik zu steuern - Einzel fast immer endet mehrere sein

Verwalten eine Verbindung (oder einen Pool von Verbindungen) zu einer Datenbank.

Ich würde es nutzen auch Informationen abzurufen und zu speichern auf externen Konfigurationsdateien.

Eine der Möglichkeiten, wie Sie einen Singleton verwenden ist eine Instanz zu decken, wo es muss ein einzelner „Makler“ seine Kontrolle des Zugangs zu einer Ressource. Singletons sind gut in Loggern, weil sie Zugang zu vermitteln, sagen wir, eine Datei, die sich ausschließlich geschrieben werden kann. Für so etwas wie die Protokollierung, sie bieten eine Möglichkeit, die Schreibvorgänge in so etwas wie eine Protokolldatei zu abstrahieren entfernt - Sie könnten einen Caching-Mechanismus, um Ihre Singleton wickeln, etc ...

Auch denken Sie an eine Situation, in der Sie eine Anwendung mit vielen Fenstern / Themen / etc, die aber einen einzigen Punkt der Kommunikation braucht. Ich habe einmal eine Arbeit zu steuern, die ich meine Bewerbung wollte zu starten. Die Singleton war verantwortlich für die Arbeitsplätze der Serialisierung und ihren Status zu einem anderen Teil des Programms anzeigt, das interessiert war. In dieser Art von Szenario können Sie zu einem Singleton aussehen als eine Art zu sein wie eine „Server“ Klasse läuft in Ihrer Anwendung ... HTH

Es sollte ein Singleton verwendet werden, wenn Zugriff auf eine Ressource verwalten, die von der gesamten Anwendung gemeinsam genutzt wird, und es wäre destruktiv sein, um möglicherweise mehrere Instanzen der gleichen Klasse. Sicherzustellen, dass der Zugriff auf gemeinsam genutzte Ressourcen Thread-sicher ist ein sehr gutes Beispiel dafür, wo diese Art von Muster von entscheidenden Bedeutung sein kann.

Wenn Singletons verwenden, sollten Sie sicherstellen, dass Sie nicht versehentlich Abhängigkeiten zu verbergen. Idealerweise werden die Singletons (wie die meisten statischen Variablen in einer Anwendung) während der Ausführung Ihres Initialisierungscode für die Anwendung (static void Main () für C # ausführbare Dateien, static void main () für Java-Programme), und dann übergeben eingerichtet, um alle anderen Klassen, die instanziiert werden, die dies erfordern. Dies hilft Ihnen, Testbarkeit halten.

Ein praktisches Beispiel für einen Singleton kann in Test :: Builder gefunden werden, die Klasse, die fast jedem modernen Perl-Test-Modul unterstützt. Der Test :: Builder Singletons speichert und Makler den Zustand und den Verlauf des Testprozesses (historische Testergebnisse, zählt die Anzahl der Tests ausführen) sowie Dinge wie, wo der Testausgang wird. Diese sind alle notwendig, mehrere Testmodule zu koordinieren, die von verschiedenen Autoren geschrieben, arbeiten zusammen in einem einzigen Testskript.

Die Geschichte des Test :: Builder Singleton ist lehrreich. Der Aufruf new() gibt Ihnen immer das gleiche Objekt. Zuerst werden alle Daten als Klassenvariablen mit nichts im Objekt selbst gespeichert. Das funktionierte, bis ich wollte mit sich selbst Test :: Builder testen. Dann brauchte ich zwei Test :: Builder Objekte, ein Setup als Attrappe, sein Verhalten und Ausgang zu erfassen und zu testen, und man das eigentliche Testobjekt zu sein. An diesem Punkt Test :: Builder wurde in ein reales Objekt umgestaltet. Das Singleton-Objekt wurde als Klassendaten gespeichert, und new() würde es immer wieder zurückkehren. create() wurde hinzugefügt, um eine neue Aufgabe zu machen und Tests ermöglichen.

Derzeit fehlen Benutzer in ihrem eigenen Modul einige Verhaltensweisen von Test :: Builder ändern, aber andere in Ruhe lassen, während die Geschichte Test gemeinsam über alle Prüfmodule bleibt. Was geschieht, ist jetzt der monolithische Test :: Builder Objekt gebrochen wird in kleinere Stücke nach unten (Geschichte, Ausgabe, Format ...) mit einem Test :: Builder Instanz sie zusammen zu sammeln. Nun Test :: Builder nicht mehr ein Singleton sein. Seine Komponenten, wie Geschichte, kann sein. Dies drückt die starre Notwendigkeit eines Singleton nach unten ein Niveau. Es gibt mehr Flexibilität für den Anwender Stücke-and-match zu mischen. Die kleineren Singleton-Objekte können jetzt speichern nur Daten, mit ihren mit Objekten zu entscheiden, wie es zu benutzen. Es ermöglicht auch eine nicht-Test :: Builder-Klasse unter Verwendung des Test :: Builder Geschichte und Ausgang Singletons zu spielen.

Es scheint, dort zu sein, ist ein Push-und Pull zwischen Koordination von Daten und Flexibilität des Verhaltens, die, indem sie die Singleton gemildert werden kann um nur gemeinsam genutzte Daten mit der kleinsten Menge von Verhalten wie möglich der Datenintegrität zu gewährleisten.

Wenn Sie eine Konfiguration laden Eigenschaften Objekt, entweder aus der Datenbank oder eine Datei, hilft es, es als Singleton zu haben; es gibt keinen Grund Re-Lektüre statische Daten zu halten, dass der Server nicht ändern, während ausgeführt wird.

Ich denke, Singletons Einsatz kann als die Viele-zu-Eins-Beziehung in Datenbanken als das gleiche gedacht werden. Wenn Sie viele verschiedene Teile des Codes, die mit einer einzigen Instanz eines Objekts arbeiten müssen, das heißt, wo es Sinn Singletons zu bedienen ist.

Wie jeder gesagt hat, eine gemeinsame Ressource -. Speziell etwas, das nicht den gleichzeitigen Zugriff verarbeiten kann

Ein konkretes Beispiel, das ich gesehen habe, ist ein Lucene Suchindex Writer.

Gemeinsame Ressourcen. Vor allem in PHP, eine Datenbank-Klasse, eine Template-Klasse, und eine globale Variable Depot-Klasse. Alle haben von allen Modulen / Klassen geteilt werden, die im gesamten Code verwendet werden.

Es ist eine wahre Objektnutzung -> die Template-Klasse die Seitenvorlage enthält, die gebaut wird, und es wird geformt, hinzugefügt, geändert durch Module, die auf Seite Ausgabe hinzufügen. Es muss als einzige Instanz gehalten werden, damit dies geschehen kann, und das gleiche gilt für Datenbanken. Mit einer gemeinsamen Datenbank Singletons, die alle Module Klassen können den Zugriff auf Anfragen bekommen und sie bekommen, ohne sie erneut ausführen zu müssen.

Ein global Variable Depot Singleton bietet Ihnen ein globales, zuverlässiges und einfach nutzbares variable Depot. Es räumt Ihren Code eine große Menge auf. Stellen Sie sich vor, die alle Konfigurationswerte in einem Array in einem Singleton wie:

$gb->config['hostname']

oder mit allen Sprachwerten in einem Array wie:

$gb->lang['ENTER_USER']

Am Ende des Codes für die Seite ausgeführt wird, erhalten Sie, sagen wir, ein jetzt reif:

$template

Singleton, ein $gb Singleton, die für den Ersatz in die lang Array hat, und alle Ausgaben geladen und schussbereit. Sie sie einfach in die Tasten ersetzen, die in reifer Seite Wertvorlage Objekt jetzt vorhanden sind, und sie dann an Benutzer absitzen.

Der große Vorteil dabei ist, Sie ANY Nachbearbeitung tun können Sie auf etwas mögen. Sie können alle Sprachwerte Rohr Google übersetzen oder einen anderen Dienst übersetzen und sie zurückbekommen, und ersetzen Sie sie in ihre Orte, übersetzt, zum Beispiel. oder können Sie in Seitenstrukturen, oder, Content-Strings ersetzen, wie Sie wollen.

Sie können Singleton verwenden, wenn der Staat Muster der Umsetzung (in der Art und Weise in dem GoF Buch gezeigt). Dies liegt daran, die konkrete Staat Klassen keinen eigenen Staat haben, und ihre Handlungen im Sinne einer Kontextklasse durchführen.

Sie können auch Abstract Factory einen Singleton machen.

Es kann sehr pragmatisch sein, spezifische Infrastruktur betrifft als Singletons oder globale Variablen zu konfigurieren. Mein Lieblingsbeispiel dafür ist Dependency Injection Frameworks, die Verwendung von Singletons machen Rahmen als Verbindungspunkt zu handeln.

In diesem Fall Sie eine Abhängigkeit von der Infrastruktur unter der Bibliothek zu vereinfachen verwenden und nicht benötigte Komplexität zu vermeiden.

ich es für ein Objekt verwenden Einkapseln Befehlszeilenparameter, wenn sie mit steckbaren Modulen handelt. Das Hauptprogramm nicht weiß, was die Befehlszeilenparameter für die Module, die geladen werden (und nicht immer einmal wissen, welche Module geladen werden). zB Hauptlasten A, die keine Parameter selbst braucht (also warum sollte es dauern, ein zusätzlicher Zeiger / reference / was auch immer, ich bin nicht sicher - sieht aus wie Verschmutzung), dann lädt Module X, Y und Z. Zwei von diesen, sagen X und Z, Notwendigkeit (oder akzeptieren) Parameter, so rufen sie zurück die Befehlszeile Singletons es zu erklären, welche Parameter zu akzeptieren, und die zur Laufzeit finden rufen sie zurück, wenn der Benutzer tatsächlich jede angegeben hat von ihnen.

In vielerlei Hinsicht ein Singleton für CGI-Parameter der Handhabung ähnlich funktionieren würde, wenn Sie verwenden einen Prozess pro Abfrage (andere mod_ * Methoden dies nicht tun, so dass es dort schlecht sein würde - so das Argument, das sagt Sie sollten nicht Singletons in der mod_cgi Welt, falls Sie Hafen zum mod_perl oder was auch immer Welt) verwenden.

Ein Beispiel mit Code, vielleicht.

Hier ist die ConcreteRegistry ein Singleton in einem Pokerspiel, das den Paketbaum Zugriff auf die wenige, Kern-Schnittstellen des Spiels (dh die Fassaden für die Modell, Ansicht, Steuerung, Umwelt, etc. das Verhalten der ganzen Weg bis erlaubt .):

http://www.edmundkirwan.com/servlet/fractal /cs1/frac-cs40.html

Ed.

1 - Ein Kommentar auf der ersten Antwort:

Ich habe nicht mit einer statischen Logger Klasse zustimmen. Dies kann für eine Implementierung praktisch sein, aber es kann für Unit-Tests nicht austauschbar sein. Eine statische Klasse kann nicht durch einen Test doppelt ersetzt werden. Wenn Sie nicht Unit-Test zu tun, werden Sie nicht sehen, nicht das Problem hier.

2 - Ich versuche, nicht einen Singleton von Hand zu erstellen. Ich schaffe nur ein einfaches Objekt mit Konstrukteuren, die mir erlauben Mitarbeiter in das Objekt zu injizieren. Wenn ich ein Singleton benötigt, würde ich eine Abhängigkeit inyection Rahmen (Spring.NET, Unity for .NET, Frühling für Java) verwenden oder eine andere.

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