Zu Entwurfsmustern: Wann sollte ich den Singleton verwenden?


447

Die verherrlichte globale Variable - wird zu einer verherrlichten globalen Klasse. Einige sagen, objektorientiertes Design zu brechen.

Geben Sie mir andere Szenarien als den guten alten Logger, in denen es sinnvoll ist, den Singleton zu verwenden.


4
Seit ich erlang gelernt habe, bevorzuge ich diesen Ansatz, nämlich Unveränderlichkeit und Nachrichtenübermittlung.
Setori

209
Was ist an dieser Frage nicht konstruktiv? Ich sehe unten eine konstruktive Antwort.
mk12

3
Ein Abhängigkeitsinjektionsframework ist ein sehr komplexer Singleton, der ein Objekt ausgibt.
Ian Ringrose

1
Singleton kann als Managerobjekt zwischen den Instanzen anderer Objekte verwendet werden. Daher sollte es nur eine Instanz des Singletons geben, in der die anderen Instanzen über die Singleton-Instanz kommunizieren sollten.
Levent Divilioglu

Ich habe eine Nebenfrage: Jede Singleton-Implementierung kann auch mit einer "statischen" Klasse (mit einer "factory" / "init" -Methode) implementiert werden - ohne tatsächlich eine Instanz einer Klasse zu erstellen (man könnte sagen, dass eine statische Klasse eine ist Art von Singleton-Implementierung, aber ...) - warum sollte man einen tatsächlichen Singleton (eine einzelne Klasseninstanz, die sicherstellt, dass sie einzeln ist) anstelle einer statischen Klasse verwenden? Der einzige Grund, an den ich denken kann, ist vielleicht "Semantik", aber selbst in diesem Sinne erfordern Singleton-Anwendungsfälle per Definition keine "Klassen-> Instanz" -Beziehung ... also ... warum?
Yuval A.

Antworten:


358

Auf meiner Suche nach der Wahrheit entdeckte ich, dass es tatsächlich nur sehr wenige "akzeptable" Gründe gibt, einen Singleton zu verwenden.

Ein Grund, der im Internet immer wieder auftaucht, ist der einer "Protokollierungs" -Klasse (die Sie erwähnt haben). In diesem Fall kann ein Singleton anstelle einer einzelnen Instanz einer Klasse verwendet werden, da eine Protokollierungsklasse normalerweise von jeder Klasse in einem Projekt immer wieder ad nauseam verwendet werden muss. Wenn jede Klasse diese Protokollierungsklasse verwendet, wird die Abhängigkeitsinjektion umständlich.

Die Protokollierung ist ein spezielles Beispiel für einen "akzeptablen" Singleton, da sie die Ausführung Ihres Codes nicht beeinflusst. Deaktivieren Sie die Protokollierung, die Codeausführung bleibt unverändert. Aktivieren Sie es genauso. Misko bringt es in Root Cause of Singletons folgendermaßen auf den Punkt : "Die Informationen hier fließen in eine Richtung: Von Ihrer Anwendung in den Logger. Obwohl Logger einen globalen Status haben, sind Logger akzeptabel, da keine Informationen von Loggern in Ihre Anwendung fließen."

Ich bin mir sicher, dass es auch andere triftige Gründe gibt. Alex Miller spricht in " Patterns I Hate " davon, dass Service Locators und clientseitige Benutzeroberflächen möglicherweise auch "akzeptable" Entscheidungen sind.

Lesen Sie mehr bei Singleton Ich liebe dich, aber du bringst mich runter.


3
@ArneMertz Ich denke, das ist der eine.
Attacktive

1
Warum können Sie nicht einfach ein globales Objekt verwenden? Warum muss es ein Singleton sein?
Schuh

1
Ich denke statische Methode für eine Protokollierung util?
Skynet

1
Singletons sind am besten geeignet, wenn Sie Ressourcen verwalten müssen. Zum Beispiel HTTP-Verbindungen. Sie möchten nicht 1 Million http-Clients für einen einzelnen Client einrichten, das ist verrückt, verschwenderisch und langsam. Ein Singleton mit einem HTTP-Client mit Verbindungspool ist also viel schneller und ressourcenschonender.
Cogman

3
Ich weiß, dass dies eine alte Frage ist, und die Informationen in dieser Antwort sind großartig. Ich habe jedoch Probleme zu verstehen, warum dies die akzeptierte Antwort ist, wenn das OP klar spezifiziert: "Geben Sie mir andere Szenarien als den guten alten Logger, in denen es sinnvoll ist, den Singleton zu verwenden."
Francisco C.

124

Ein Singleton-Kandidat muss drei Anforderungen erfüllen:

  • Steuert den gleichzeitigen Zugriff auf eine gemeinsam genutzte Ressource.
  • Der Zugriff auf die Ressource wird von mehreren unterschiedlichen Teilen des Systems angefordert.
  • Es kann nur ein Objekt geben.

Wenn Ihr vorgeschlagener Singleton nur eine oder zwei dieser Anforderungen hat, ist eine Neugestaltung fast immer die richtige Option.

Beispielsweise ist es unwahrscheinlich, dass ein Druckerspooler von mehr als einer Stelle (dem Menü Drucken) aufgerufen wird, sodass Sie Mutexe verwenden können, um das Problem des gleichzeitigen Zugriffs zu lösen.

Ein einfacher Logger ist das offensichtlichste Beispiel für einen möglicherweise gültigen Singleton. Dies kann sich jedoch bei komplexeren Protokollierungsschemata ändern.


3
Ich bin mit Punkt 2 nicht einverstanden. Punkt 3 ist nicht wirklich ein Grund (nur weil Sie es können, heißt das nicht, dass Sie es sollten) und 1 ist ein guter Punkt, aber ich sehe immer noch keine Verwendung dafür. Nehmen wir an, die gemeinsam genutzte Ressource ist ein Festplattenlaufwerk oder ein Datenbankcache. Sie können ein anderes Laufwerk hinzufügen oder einen Datenbank-Cache haben, der sich auf eine andere Sache konzentriert (z. B. einen Cache für eine spezialisierte Tabelle für einen Thread, wobei der andere allgemeiner ist).

15
Ich denke, Sie haben das Wort "Kandidat" verpasst. Ein Singleton-Kandidat muss die drei Anforderungen erfüllen. Nur weil etwas den Anforderungen entspricht, heißt das nicht, dass es ein Singleton sein sollte. Es kann andere
Designfaktoren geben

45

Lesen von Konfigurationsdateien, die nur zum Startzeitpunkt gelesen werden sollten, und Einkapseln in einen Singleton.


8
Ähnlich wie Properties.Settings.Defaultin .NET.
Nick Bedford

9
@Paul, Das "No-Singleton-Camp" gibt an, dass das Konfigurationsobjekt einfach an Funktionen übergeben werden soll, die es benötigen, anstatt es global zugänglich zu machen (auch bekannt als Singleton).
Pacerier

2
Nicht zustimmen. Sollte die Konfiguration in die Datenbank verschoben werden, ist alles durcheinander. Sollte der Pfad zur Konfiguration von etwas außerhalb dieses Singletons abhängen, müssen diese Dinge auch statisch sein.
rr-

3
@PaulCroarkin Können Sie dies erweitern und erklären, wie vorteilhaft dies ist?
AlexG

1
@ rr- Wenn die Konfiguration in die Datenbank verschoben wird, kann sie weiterhin in ein Konfigurationsobjekt gekapselt werden, das an Funktionen übergeben wird, die sie benötigen. (PS Ich bin nicht im "No-Singleton" -Lager).
Will Sheppard

36

Sie verwenden einen Singleton, wenn Sie eine gemeinsam genutzte Ressource verwalten müssen. Zum Beispiel ein Druckerspooler. Ihre Anwendung sollte nur eine einzige Instanz des Spoolers haben, um widersprüchliche Anforderungen für dieselbe Ressource zu vermeiden.

Oder eine Datenbankverbindung oder ein Dateimanager usw.


30
Ich habe dieses Beispiel eines Druckerspoolers gehört und finde es irgendwie lahm. Wer sagt, dass ich nicht mehr als einen Spooler haben kann? Was zum Teufel ist ein Druckerspooler überhaupt? Was ist, wenn ich verschiedene Druckertypen habe, die keine Konflikte verursachen oder unterschiedliche Treiber verwenden können?
1800 INFORMATION

6
Es ist nur ein Beispiel ... für jede Situation, die jemand als Beispiel verwendet, können Sie ein alternatives Design finden, das das Beispiel unbrauchbar macht. Stellen wir uns vor, der Spooler verwaltet eine einzelne Ressource, die von mehreren Komponenten gemeinsam genutzt wird. Es klappt.
Vincent Ramdhanie

2
Es ist das klassische Beispiel für die Viererbande. Ich denke, eine Antwort mit einem wirklich erprobten Anwendungsfall wäre nützlicher. Ich meine eine Situation, in der Sie tatsächlich der Meinung waren, dass der Singleton die beste Lösung ist.
Andrei Vajna II

Eine gemeinsame Ressource ist meiner Meinung nach ein viel zu weites Beispiel. Wie würden Sie testen, ob die Objekte, die den Druckspooler verwenden, angesichts eines fehlerhaften Spoolers ordnungsgemäß funktionieren, wenn Sie keine fehlerhafte Implementierung von 'Spooler' injizieren können? Obwohl kurz und nicht informativ, ist die akzeptierte Antwort in meinem Buch ein viel sicherer Ansatz
Rune FS

Was zum Teufel ist ein Druckerspooler?
RayLoveless

23

Schreibgeschützte Singletons, die einen globalen Status (Benutzersprache, Hilfedateipfad, Anwendungspfad) speichern, sind sinnvoll. Seien Sie vorsichtig, wenn Sie Singletons zur Steuerung der Geschäftslogik verwenden - Single ist fast immer mehrfach


4
Die Benutzersprache kann nur Singleton sein, vorausgesetzt, dass nur ein Benutzer das System verwenden kann.
Samuel Åslund

… Und dass ein Benutzer nur eine Sprache spricht.
Spektren

17

Verwalten einer Verbindung (oder eines Pools von Verbindungen) zu einer Datenbank.

Ich würde es auch verwenden, um Informationen in externen Konfigurationsdateien abzurufen und zu speichern.


2
Wäre ein Datenbankverbindungsgenerator nicht ein Beispiel für eine Factory?
Ken

3
@ Ken Sie möchten, dass diese Fabrik in fast allen Fällen ein Singleton ist.
Chris Marisic

2
@Federico, Das "No-Singleton-Camp" gibt an, dass diese Datenbankverbindungen einfach an Funktionen übergeben werden sollen, die sie benötigen, anstatt sie global zugänglich zu machen (auch bekannt als Singleton).
Pacerier

3
Dafür brauchst du eigentlich keinen Singleton. Es kann injiziert werden.
Nestor Ledon

11

Eine Möglichkeit, einen Singleton zu verwenden, besteht darin, eine Instanz abzudecken, in der ein einzelner "Broker" den Zugriff auf eine Ressource steuern muss. Singletons eignen sich gut für Logger, da sie beispielsweise den Zugriff auf eine Datei vermitteln, in die nur exklusiv geschrieben werden kann. Für etwas wie die Protokollierung bieten sie eine Möglichkeit, die Schreibvorgänge in eine Protokolldatei zu abstrahieren - Sie können einen Caching-Mechanismus in Ihren Singleton usw. einbinden.

Denken Sie auch an eine Situation, in der Sie eine Anwendung mit vielen Fenstern / Threads / usw. haben, die jedoch einen einzigen Kommunikationspunkt benötigt. Ich habe einmal einen verwendet, um Jobs zu steuern, bei denen meine Anwendung gestartet werden soll. Der Singleton war dafür verantwortlich, die Jobs zu serialisieren und ihren Status jedem anderen Teil des Programms anzuzeigen, der interessiert war. In einem solchen Szenario können Sie einen Singleton als eine Art "Server" -Klasse betrachten, die in Ihrer Anwendung ausgeführt wird ... HTH


3
Logger sind meistens Singletons, sodass Logging-Objekte nicht weitergegeben werden müssen. Jede anständige Implementierung eines Protokolldatenstroms stellt sicher, dass gleichzeitige Schreibvorgänge nicht möglich sind, unabhängig davon, ob es sich um einen Singleton handelt oder nicht.
Metao

10

Ein Singleton sollte verwendet werden, wenn der Zugriff auf eine Ressource verwaltet wird, die von der gesamten Anwendung gemeinsam genutzt wird, und es wäre destruktiv, wenn möglicherweise mehrere Instanzen derselben Klasse vorhanden wären. Die Sicherstellung, dass der Zugriff auf gemeinsam genutzte Ressourcen threadsicher ist, ist ein sehr gutes Beispiel dafür, wo diese Art von Muster von entscheidender Bedeutung sein kann.

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


8

Ich denke, die Verwendung von Singleton kann als die gleiche wie die Viele-zu-Eins-Beziehung in Datenbanken angesehen werden. Wenn Sie viele verschiedene Teile Ihres Codes haben, die mit einer einzelnen Instanz eines Objekts arbeiten müssen, ist es sinnvoll, Singletons zu verwenden.


6

Ein praktisches Beispiel für einen Singleton finden Sie in Test :: Builder , der Klasse, die nahezu jedes moderne Perl-Testmodul unterstützt. Der Test :: Builder-Singleton speichert und vermittelt den Status und den Verlauf des Testprozesses (historische Testergebnisse, zählt die Anzahl der ausgeführten Tests) sowie Dinge wie die Testausgabe. Diese sind alle erforderlich, um mehrere Testmodule zu koordinieren, die von verschiedenen Autoren geschrieben wurden, um in einem einzigen Testskript zusammenzuarbeiten.

Die Geschichte von Test :: Builders Singleton ist lehrreich. Wenn new()Sie anrufen, erhalten Sie immer das gleiche Objekt. Zunächst wurden alle Daten als Klassenvariablen mit nichts im Objekt selbst gespeichert. Dies funktionierte, bis ich Test :: Builder mit sich selbst testen wollte. Dann brauchte ich zwei Test :: Builder-Objekte, eines als Dummy, um sein Verhalten und seine Ausgabe zu erfassen und zu testen, und eines, um das eigentliche Testobjekt zu sein. Zu diesem Zeitpunkt wurde Test :: Builder in ein reales Objekt umgestaltet. Das Singleton-Objekt wurde als Klassendaten gespeichert und gab new()es immer zurück. create()wurde hinzugefügt, um ein neues Objekt zu erstellen und das Testen zu ermöglichen.

Derzeit möchten Benutzer einige Verhaltensweisen von Test :: Builder in ihrem eigenen Modul ändern, andere jedoch in Ruhe lassen, während der Testverlauf für alle Testmodule gleich bleibt. Was jetzt passiert, ist, dass das monolithische Test :: Builder-Objekt in kleinere Teile (Verlauf, Ausgabe, Format ...) zerlegt wird, die von einer Test :: Builder-Instanz zusammengetragen werden. Jetzt muss Test :: Builder kein Singleton mehr sein. Seine Komponenten können wie die Geschichte sein. Dies drückt die unflexible Notwendigkeit eines Singletons auf eine Ebene. Es gibt dem Benutzer mehr Flexibilität beim Mischen und Anpassen von Teilen. Die kleineren Singleton-Objekte können jetzt nur noch Daten speichern, wobei ihre enthaltenen Objekte entscheiden, wie sie verwendet werden sollen. Es ermöglicht sogar einer Nicht-Test :: Builder-Klasse, mitzuspielen, indem der Test :: Builder-Verlauf verwendet und Singletons ausgegeben werden.

Es scheint ein Push-and-Pull zwischen der Koordination von Daten und der Flexibilität des Verhaltens zu geben, das gemindert werden kann, indem der Singleton nur gemeinsam genutzte Daten mit möglichst wenig Verhalten umgibt, um die Datenintegrität sicherzustellen.


5

Wenn Sie ein Konfigurationseigenschaftsobjekt entweder aus der Datenbank oder einer Datei laden, ist es hilfreich, es als Singleton zu haben. Es gibt keinen Grund, statische Daten, die sich während der Ausführung des Servers nicht ändern, erneut zu lesen.


2
Warum sollten Sie die Daten nicht nur einmal laden und das Konfigurationsobjekt nach Bedarf übergeben?
Lagweezle

Was ist mit dem Herumreichen ??? Wenn ich jedes Objekt
herumgeben

@Enerccio Wenn Sie Objekte haben, die auf 20 verschiedenen anderen Objekten ohne Kapselung basieren, haben Sie bereits große Designprobleme.
Spektren

@spectras Muss ich? Wenn ich den GUI-Dialog implementiere, benötige ich: Repository, Lokalisierung, Sitzungsdaten, Anwendungsdaten, übergeordnetes Widget, Clientdaten, Berechtigungsmanager und wahrscheinlich mehr. Sicher, Sie können einige aggregieren, aber warum? Persönlich verwende ich Frühling und Aspekte, um all diese Abhängigkeiten automatisch in die Widget-Klasse zu verdrahten, und das entkoppelt alles.
Enerccio

Wenn Sie so viel Status haben, können Sie eine Fassade implementieren, um einen Blick auf relevante Aspekte des spezifischen Kontexts zu werfen. Warum? Weil es ein sauberes Design ohne die Antimuster von Singleton- oder 29-Arg-Konstruktoren ermöglichen würde. Gerade die Tatsache, dass Ihr GUI-Dialog auf all diese Dinge zugreift, schreit "Verstoß gegen das Prinzip der Einzelverantwortung".
Spektren

3

Wie jeder gesagt hat, eine gemeinsam genutzte Ressource - insbesondere etwas, das keinen gleichzeitigen Zugriff verarbeiten kann.

Ein spezielles Beispiel, das ich gesehen habe, ist ein Lucene Search Index Writer.


1
Und doch ist IndexWriter kein Singleton ...
Mark

3

Sie können Singleton verwenden, wenn Sie das Statusmuster implementieren (wie im GoF-Buch gezeigt). Dies liegt daran, dass die konkreten Statusklassen keinen eigenen Status haben und ihre Aktionen in Form einer Kontextklasse ausführen.

Sie können Abstract Factory auch zu einem Singleton machen.


Dies ist der Fall, mit dem ich mich jetzt in einem Projekt beschäftige. Ich habe ein Statusmuster verwendet, um sich wiederholenden bedingten Code aus den Methoden des Kontexts zu entfernen. Die Staaten haben keine eigenen Instanzvariablen. Ich bin jedoch auf dem Zaun, ob ich sie zu Singletons machen soll. Jedes Mal, wenn der Status wechselt, wird eine neue Instanz instanziiert. Dies erscheint verschwenderisch, da sich die Instanz auf keinen Fall von einer anderen unterscheiden kann (da keine Instanzvariablen vorhanden sind). Ich versuche herauszufinden, warum ich es nicht benutzen sollte.
Kiwicomb123

1
@ kiwicomb123 Versuchen Sie setState(), sich für die Entscheidung über die Richtlinie zur Erstellung des Staates verantwortlich zu machen . Es ist hilfreich, wenn Ihre Programmiersprache Vorlagen oder Generika unterstützt. Anstelle von Singleton können Sie auch das Monostate- Muster verwenden, bei dem beim Instanziieren eines Statusobjekts dasselbe globale / statische Statusobjekt wiederverwendet wird. Die Syntax zum Ändern des Status kann unverändert bleiben, da Ihre Benutzer nicht wissen müssen, dass der instanziierte Status ein Monostate ist.
Emile Cormier

Okay, in meinen Zuständen könnte ich einfach alle Methoden statisch machen. Wenn also eine neue Instanz erstellt wird, hat sie nicht den gleichen Overhead? Ich bin etwas verwirrt, ich muss mich über das Monostate-Muster informieren.
Kiwicomb123

@ kiwicomb123 Nein, bei Monostate geht es nicht darum, alle Mitglieder statisch zu machen. Besser, Sie lesen es nach und überprüfen SO auf verwandte Fragen und Antworten.
Emile Cormier

Ich denke, das sollte mehr Stimmen haben. Abstrakte Factory ist häufig genug, und da Fabriken zustandslos und zustandslos sind und nicht mit statischen Methoden (in Java) implementiert werden können, die nicht überschrieben werden, sollte die Verwendung von Singleton in Ordnung sein.
DPM

3

Geteilte Ressourcen. Insbesondere in PHP eine Datenbankklasse, eine Vorlagenklasse und eine globale variable Depotklasse. Alle müssen von allen Modulen / Klassen gemeinsam genutzt werden, die im gesamten Code verwendet werden.

Es handelt sich um eine echte Objektverwendung -> Die Vorlagenklasse enthält die Seitenvorlage, die erstellt wird, und wird durch Module, die zur Seitenausgabe hinzugefügt werden, geformt, hinzugefügt und geändert. Es muss als einzelne Instanz aufbewahrt werden, damit dies geschehen kann, und das Gleiche gilt für Datenbanken. Mit einem gemeinsam genutzten Datenbank-Singleton können die Klassen aller Module auf Abfragen zugreifen und diese abrufen, ohne sie erneut ausführen zu müssen.

Ein Singleton mit globalem Variablendepot bietet Ihnen ein globales, zuverlässiges und einfach zu verwendendes Variablendepot. Es räumt Ihren Code sehr auf. Stellen Sie sich vor, Sie haben alle Konfigurationswerte in einem Array in einem Singleton wie folgt:

$gb->config['hostname']

oder alle Sprachwerte in einem Array haben wie:

$gb->lang['ENTER_USER']

Am Ende der Ausführung des Codes für die Seite erhalten Sie beispielsweise eine jetzt ausgereifte:

$template

Singleton, a $gb Singleton, in den das lang-Array zum Ersetzen eingefügt und alle Ausgaben geladen und bereit sind. Sie ersetzen sie einfach durch die Schlüssel, die jetzt im Seitenwert des ausgereiften Vorlagenobjekts vorhanden sind, und stellen sie dann dem Benutzer zur Verfügung.

Der große Vorteil davon ist, dass Sie JEDE Nachbearbeitung durchführen können, die Sie für alles mögen. Sie können alle Sprachwerte an Google Übersetzer oder einen anderen Übersetzungsdienst weiterleiten und sie zurückerhalten und an ihren Stellen ersetzen, z. B. übersetzt. Sie können auch Seitenstrukturen oder Inhaltszeichenfolgen nach Belieben ersetzen.


21
Möglicherweise möchten Sie Ihre Antwort in mehrere Absätze aufteilen und die Codesegmente aus Gründen der Lesbarkeit blockieren.
Justin

1

Es kann sehr pragmatisch sein, bestimmte Infrastrukturprobleme als Singletons oder globale Variablen zu konfigurieren. Mein Lieblingsbeispiel hierfür sind Dependency Injection-Frameworks, die Singletons verwenden, um als Verbindungspunkt zum Framework zu fungieren.

In diesem Fall sind Sie von der Infrastruktur abhängig, um die Verwendung der Bibliothek zu vereinfachen und unnötige Komplexität zu vermeiden.


0

Ich benutze es für ein Objekt, das Befehlszeilenparameter kapselt, wenn es um steckbare Module geht. Das Hauptprogramm kennt die Befehlszeilenparameter für geladene Module nicht (und weiß nicht immer, welche Module geladen werden). Beispiel: Hauptlasten A, die selbst keine Parameter benötigen (warum also ein zusätzlicher Zeiger / Referenz / was auch immer benötigt wird, ich bin mir nicht sicher - sieht nach Verschmutzung aus), laden dann die Module X, Y und Z. Zwei Von diesen, z. B. X und Z, benötigen (oder akzeptieren) Parameter, sodass sie den Befehlszeilen-Singleton zurückrufen, um ihm mitzuteilen, welche Parameter akzeptiert werden sollen, und zur Laufzeit zurückrufen, um herauszufinden, ob der Benutzer tatsächlich irgendwelche angegeben hat von ihnen.

In vielerlei Hinsicht würde ein Singleton für die Behandlung von CGI-Parametern ähnlich funktionieren, wenn Sie nur einen Prozess pro Abfrage verwenden (andere mod_ * -Methoden tun dies nicht, daher wäre es dort schlecht - daher das Argument, dass Sie es nicht tun sollten. Verwenden Sie keine Singletons in der mod_cgi-Welt, falls Sie auf mod_perl oder eine andere Welt portieren.


-1

Vielleicht ein Beispiel mit Code.

Hier ist die ConcreteRegistry ein Singleton in einem Pokerspiel, das es den Verhaltensweisen bis zum Ende des Paketbaums ermöglicht, auf die wenigen Kernschnittstellen des Spiels (dh die Fassaden für das Modell, die Ansicht, den Controller, die Umgebung usw.) zuzugreifen:

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

Ed.


1
Die Verbindung ist jetzt unterbrochen. Wenn Sie jedoch Ansichtsinformationen in einem Singleton registrieren, auf den in der gesamten Anwendung zugegriffen wird, fehlt der MVC-Punkt. Eine Ansicht wird von einem Controller aktualisiert (und kommuniziert mit diesem), der das Modell verwendet. Wie es hier klingt, ist es wahrscheinlich ein Missbrauch von Singleton und ein Refactoring ist angebracht.
Drharris

-9

1 - Ein Kommentar zur ersten Antwort:

Ich bin mit einer statischen Logger-Klasse nicht einverstanden. Dies kann für eine Implementierung praktisch sein, kann jedoch nicht für Komponententests ersetzt werden. Eine statische Klasse kann nicht durch ein Testdouble ersetzt werden. Wenn Sie keinen Unit-Test durchführen, wird das Problem hier nicht angezeigt.

2 - Ich versuche, keinen Singleton von Hand zu erstellen. Ich erstelle einfach ein einfaches Objekt mit Konstruktoren, mit denen ich Mitarbeiter in das Objekt einfügen kann. Wenn ich einen Singleton benötige, würde ich ein Abhängigkeits-Inyection-Framework (Spring.NET, Unity für .NET, Spring für Java) oder ein anderes verwenden.


11
Sie sollten Antworten direkt kommentieren, indem Sie auf den Link unten in einer Antwort klicken. es ist viel einfacher so zu lesen. Auch die Antwort, die Sie oben gesehen haben, ist wahrscheinlich nicht die erste. Die Antworten werden ständig neu geordnet.
Ross

Warum sollten Sie eine Unit-Test-Protokollierung wünschen?
Enerccio

Es gibt einen großen Unterschied zwischen "einer statischen Logger-Klasse" und einer statischen Logger- Instanz . Das Singleton-Muster sagt nicht "mach deine Klasse statisch", sondern "Zugriff auf die Instanz eines Objekts statisch". So zum Beispiel, ILogger logger = Logger.SingleInstance();wo diese Methode statisch ist und es gibt eine statisch gespeicherte Instanz eines ILogger. Sie haben das Beispiel eines "Abhängigkeitsinjektions-Frameworks" verwendet. Fast alle DI-Container sind Singletons; Ihre Konfigurationen werden statisch definiert und letztendlich von einer einzigen Dienstanbieterschnittstelle aus abgerufen / gespeichert.
Jon Davis
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.