Wir haben eine Klasse, die Konfigurationsinformationen für die Anwendung enthält. Früher war es ein Singleton. Nach einigen architektonischen Überprüfungen wurde uns gesagt, wir sollten den Singleton entfernen. Wir haben einige Vorteile gesehen, wenn Singleton beim Komponententest nicht verwendet wurde, da wir verschiedene Konfigurationen gleichzeitig testen können.
Ohne Singleton müssen wir die Instanz überall in unserem Code weitergeben. Es wird so chaotisch, dass wir einen Singleton-Wrapper geschrieben haben. Jetzt portieren wir denselben Code nach PHP und .NET. Ich frage mich, ob es ein besseres Muster gibt, das wir für das Konfigurationsobjekt verwenden können.
quelle
Am besten verwenden Sie stattdessen ein Factory-Muster. Wenn Sie eine neue Instanz Ihrer Klasse (in der Factory) erstellen, können Sie die 'globalen' Daten in das neu erstellte Objekt einfügen, entweder als Referenz auf eine einzelne Instanz (die Sie in der Factory-Klasse speichern) oder indem Sie die entsprechenden kopieren Daten in das neue Objekt.
Alle Ihre Objekte enthalten dann die Daten, die früher im Singleton lebten. Ich glaube nicht, dass es insgesamt einen großen Unterschied gibt, aber es kann das Lesen Ihres Codes erleichtern.
quelle
Ich sage hier vielleicht das Offensichtliche, aber gibt es einen Grund, warum Sie kein Abhängigkeitsinjektions-Framework wie z Spring oder Guice verwenden können ? (Ich glaube, Spring ist jetzt auch für .NET verfügbar).
Auf diese Weise kann das Framework eine einzelne Kopie der Konfigurationsobjekte enthalten, und Ihre Beans (Dienste, DAOs usw.) müssen sich nicht darum kümmern, sie nachzuschlagen.
Dies ist der Ansatz, den ich normalerweise verfolge!
quelle
Wenn Sie Spring Framework verwenden , können Sie einfach eine reguläre Bean erstellen. Standardmäßig (oder wenn Sie dies explizit festlegen
scope="singleton"
) wird nur eine Instanz der Bean erstellt und diese Instanz wird jedes Mal zurückgegeben, wenn die Bean in einer Abhängigkeit verwendet oder über abgerufen wirdgetBean()
.Sie erhalten den Vorteil der einzelnen Instanz ohne die Kopplung des Singleton-Musters.
quelle
Die Alternative besteht darin, das zu übergeben, was Sie benötigen, anstatt ein Objekt nach Dingen zu fragen.
quelle
Sammeln Sie keine Verantwortlichkeiten für ein einzelnes Konfigurationsobjekt da dies zu einem sehr großen Objekt führt, das sowohl schwer zu verstehen als auch fragil ist.
Wenn Sie beispielsweise einen anderen Parameter für eine bestimmte Klasse benötigen, ändern Sie das
Configuration
Objekt und kompilieren alle Klassen, die es verwenden, neu. Das ist etwas problematisch.Versuchen Sie, Ihren Code umzugestalten, um ein gemeinsames, globales und großes
Configuration
Objekt zu vermeiden . Übergeben Sie nur die erforderlichen Parameter an Clientklassen:sollte überarbeitet werden, um:
Ein Abhängigkeitsinjektions-Framework wird hier viel helfen, ist aber nicht unbedingt erforderlich.
quelle
Sie können das gleiche Verhalten von Singleton mithilfe statischer Methoden erzielen. Steve Yegge erklärt es sehr gut in diesem Beitrag.
quelle
Ist eine Klasse möglich, die nur statische Methoden und Felder enthält? Ich bin mir nicht sicher, wie genau Ihre Situation ist, aber es könnte sich lohnen, sie zu untersuchen.
quelle
Hängt davon ab, welche Werkzeuge / Frameworks usw. verwendet werden. Mit Tools für Abhängigkeitsinjektion / ioc kann man häufig immer noch Singleton-Leistung / -Optimierungen erzielen, indem der di / ioc-Container das Singleton-Verhalten für die erforderliche Klasse verwendet (z. B. eine IConfigSettings-Schnittstelle), indem immer nur eine Instanz der Klasse erstellt wird. Dies könnte zum Testen noch ersetzt werden
Alternativ kann eine Factory verwendet werden, um die Klasse zu erstellen und jedes Mal dieselbe Instanz zurückzugeben, wenn Sie sie anfordern. Zum Testen kann jedoch eine stubbed / verspottete Version zurückgegeben werden
quelle
Überprüfen Sie die Möglichkeit, die Konfiguration als Rückrufschnittstelle vorzunehmen. Ihr konfigurationssensitiver Code sieht also folgendermaßen aus:
Der System-Init-Code sieht folgendermaßen aus:
quelle
Sie können ein Abhängigkeitsinjektionsframework verwenden, um das Übergeben des Konfigurationsobjekts zu erleichtern. Ein anständiges ist ninject, das den Vorteil hat, Code anstelle von XML zu verwenden.
quelle
Vielleicht auch nicht sehr sauber, aber Sie könnten vielleicht die Informationsbits, die Sie geändert haben möchten, an die Methode übergeben, die den Singleton erstellt - anstatt zu verwenden
Sie können
createSingleton(Information info)
direkt beim Start der Anwendung aufrufen (und in den setUp-Methoden der Unit-Tests).quelle
Singletons sind nicht böse, aber das Designmuster ist fehlerhaft. Ich habe eine Klasse, die ich zur Laufzeit nur eine einzige Instanz davon erstellen möchte, während des Komponententests jedoch mehrere isolierte Instanzen erstellen möchte, um deterministische Ergebnisse sicherzustellen.
DI mit Spring usw. ist eine sehr gute Option, aber nicht die einzige.
quelle