Singleton mit Argumenten in Java
Las ich die Singleton-Artikel auf Wikipedia und stieß ich auf dieses Beispiel:
public class Singleton {
//Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
Während ich mag wirklich die Art wie das Singleton verhält, kann ich nicht sehen, wie sich anzupassen, zu integrieren, die Argumente an den Konstruktor übergeben. Was ist der bevorzugte Weg, um dies in Java? Würde ich so etwas tun?
public class Singleton
{
private static Singleton singleton = null;
private final int x;
private Singleton(int x) {
this.x = x;
}
public synchronized static Singleton getInstance(int x) {
if(singleton == null) singleton = new Singleton(x);
return singleton;
}
}
Dank!
Edit: ich denke ich habe angefangen, einen Sturm der Kontroverse mit meinem Wunsch, Singleton. Lassen Sie mich erklären, meine motivation und ich hoffe jemand kann deuten auf eine bessere Idee. Ich bin mit einem grid-computing-framework zur Ausführung von Aufgaben parallel. Im Allgemeinen, ich habe so etwas wie dieses:
//AbstractTask implements Serializable
public class Task extends AbstractTask
{
private final ReferenceToReallyBigObject object;
public Task(ReferenceToReallyBigObject object)
{
this.object = object;
}
public void run()
{
//Do some stuff with the object (which is immutable).
}
}
Was passiert, ist, dass, obwohl ich lediglich übergeben Sie einen Verweis, um meine Daten zu allen Aufgaben, wenn die Aufgaben serialisiert die Daten, kopiert wird immer und immer wieder. Was ich will zu tun ist, teilen sich das Objekt unter all den Aufgaben. Natürlich könnte ich die Klasse ändern, und zwar so:
//AbstractTask implements Serializable
public class Task extends AbstractTask
{
private static ReferenceToReallyBigObject object = null;
private final String filePath;
public Task(String filePath)
{
this.filePath = filePath;
}
public void run()
{
synchronized(this)
{
if(object == null)
{
ObjectReader reader = new ObjectReader(filePath);
object = reader.read();
}
}
//Do some stuff with the object (which is immutable).
}
}
Wie Sie sehen können, auch hier habe ich das Problem, dass man einen anderen Datei-Pfad bedeutet, dass nichts nach das erste ist vergangen. Das ist, warum ich mag die Idee für ein storedie veröffentlicht wurde in den Antworten. Jedenfalls, als auch die Logik für das laden der Datei in der run-Methode, ich wollte diese abstrakte Logik in einer Singleton-Klasse. Ich werde nicht bieten noch ein weiteres Beispiel, aber ich hoffe, Sie bekommen die Idee. Bitte lassen Sie mich hören Ihren Ideen für eine elegantere Möglichkeit das zu erreichen, was ich zu tun versuche. Danke nochmals!
InformationsquelleAutor der Frage | 2009-06-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich werde meinen Punkt sehr klar: ein singleton mit Parameter ist nicht ein singleton.
Singleton ist, per definition, ist ein Objekt, das Sie möchten, um instanziiert zu werden, nicht mehr als einmal. Wenn Sie versuchen, zu füttern Parameter dem Konstruktor übergeben, was ist der Punkt, der die singleton?
Haben Sie zwei Möglichkeiten. Wenn Sie möchten, dass Ihre singleton initialisiert werden mit einigen Daten haben, können Sie laden Sie es mit Daten nach der Instanziierungetwa so:
Wenn der Betrieb singleton ist die Durchführung wiederholt und mit unterschiedlichen Parametern jedes mal, genauso gut könnte man die übergabe der Parameter an die main-Methode ausgeführt wird:
In jedem Fall die Instanziierung wird immer parameter-weniger. Ansonsten singleton ist kein singleton.
InformationsquelleAutor der Antwort Yuval Adam
Ich glaube, Sie brauchen so etwas wie eine Fabrik Objekte mit verschiedenen Parametern instanziiert und wiederverwendet werden. Es könnte umgesetzt werden, indem eine synchronisierte
HashMap
oderConcurrentHashMap
Karte einen parameter (eineInteger
für ein Beispiel), um Ihre 'singleton' parametrisierbare Klasse.Obwohl Sie vielleicht an dem Punkt, wo Sie verwenden sollten regelmäßige, nicht-singleton-Klassen statt (zum Beispiel benötigen 10.000 unterschiedlich parametrisiert singleton).
Hier ist ein Beispiel für einen solchen Shop:
Schieben Sie es noch weiter, die Java
enum
s können ebenfalls berücksichtigt werden (oder als) eingestellt singletons, obwohl es nur eine Feste Anzahl statischer Varianten.Allerdings, wenn Sie brauchen eine verteilte1 Lösung, betrachten wir einige seitliche caching-Lösung. Zum Beispiel: EHCache von Terracotta etc.
1 im Sinne von, die sich über mehrere VMs auf wohl mehreren Computern.
InformationsquelleAutor der Antwort akarnokd
Können Sie auch mit dem Builder-Muster, wenn Sie möchten, um zu zeigen, dass einige Parameter sind obligatorisch.
Dann könnte man erstellen/instanziieren/eingestellt es wie folgt:
InformationsquelleAutor der Antwort gerardnico
Verwenden Getter und setter auf die variable setzen und den default-Konstruktor privat. Dann verwenden:
InformationsquelleAutor der Antwort AlbertoPL
Überrascht, dass niemand erwähnt, wie ein logger erstellt/abgerufen werden. Für das Beispiel unten zeigt, wie Log4J-logger abgerufen werden.
Es gibt einige Ebenen der indirections, aber das wichtige ist unten Methodedie ziemlich viel sagt alles darüber, wie es funktioniert. Es verwendet eine hash-Tabelle zum speichern die verlassen-Logger und der Schlüssel ist abgeleitet von dem Namen. Wenn der logger nicht vorhanden ist für einen Namen, es verwendet eine factory zum erstellen der logger und dann fügt es zu der hash-Tabelle.
InformationsquelleAutor der Antwort wanghq
Änderung des Singleton-Muster verwendet Bill Pugh der initialization on demand holder idiom. Dies ist thread-sicher, ohne den Aufwand für spezielle Sprachkonstrukte (d.h. flüchtige oder synchronisiert):
InformationsquelleAutor der Antwort tekumara
Können Sie eine Initialisierungs-Methode zu trennen Instanziierung von bekommen.
Dann rufen Sie
Singleton.init(123)
einmal von irgendwo, um ihn zu konfigurieren, in Ihrer app-Start zum Beispiel.InformationsquelleAutor der Antwort miguel
Der Grund, warum Sie keinen Sinn machen, wie das zu erreichen, was Sie versuchen zu tun, ist wohl, dass das, was Sie zu tun versuchen, nicht wirklich sinnvoll. Sie möchten rufen Sie
getInstance(x)
mit verschiedenen Argumenten, aber immer wieder das gleiche Objekt? Welches Verhalten wollen Sie, wenn Sie anrufengetInstance(2)
und danngetInstance(5)
?Wenn Sie möchten, dass das gleiche Objekt, aber für seine inneren Wert, anders zu sein, das ist der einzige Weg, es ist immer noch ein singleton ist, dann brauchen Sie nicht zu kümmern, die Konstruktor; Sie setzen Sie einfach den Wert in
getInstance()
auf das Objekt aus. Natürlich, Sie verstehen, dass alle anderen Referenzen auf das singleton-hab jetzt auch eine andere interne Wert.Wenn Sie wollen
getInstance(2)
undgetInstance(5)
zurück verschiedene Objekte, auf der anderen Seite, Sie sind nicht mit dem Singleton-pattern, bist du mit dem Factory-pattern.InformationsquelleAutor der Antwort chaos
In deinem Beispiel sind Sie nicht mit einem singleton. Beachten Sie, dass, wenn Sie Folgendes tun (unter der Annahme, dass das Singleton.getInstance war eigentlich statisch):
Dann die obj2.x-Werte ist 3, nicht 4. Wenn Sie brauchen, um dies zu tun, stellen Sie eine nur-Klasse. Wenn die Anzahl der Werte klein ist und behoben wird, können Sie erwägen, einen
enum
. Wenn Sie Probleme mit übermäßiger Objekt generation (was normalerweise nicht der Fall ist), dann kannst du überlegen, caching-Werte (und überprüfen Quellen oder Hilfe bekommen, wie es offensichtlich ist, wie das erstellen von caches ohne die Gefahr von memory leaks).Vielleicht möchten Sie auch zu Lesen Sie diesen Artikel als singletons kann sehr leicht überstrapaziert.
InformationsquelleAutor der Antwort Kathy Van Stone
Einem anderen Grund Singletons sind ein anti-pattern ist, dass, wenn geschrieben, den Empfehlungen entsprechend, mit privatem Konstruktor, Sie sind sehr schwer zu Unterklasse und konfigurieren, um die Verwendung, in bestimmten unit-tests. Erforderlich wäre, in die Pflege von legacy-code, zum Beispiel.
InformationsquelleAutor der Antwort JosefB
Nehmen wir das problem "how to make singleton mit Zustand", dann ist es nicht notwendig, um pass den Staat als Konstruktor-parameter. Ich Stimme mit der Beiträge, die Initialisierung der Mitgliedstaaten oder über eine set-Methode, nachdem die singleton-Instanz.
Andere Frage ist: ist es gut, ein singleton mit dem Staat?
InformationsquelleAutor der Antwort user3014901
"Ein singleton mit Parameter ist nicht ein singleton" - Anweisung ist nicht ganz korrekt. Wir müssen analysieren, dies aus der Perspektive der Anwendung statt, die aus der code-Sicht.
Bauen wir eine singleton Klasse zu erstellen, die eine einzelne Instanz von einem Objekt in einer Anwendung ausführen. Durch einen Konstruktor mit parameter, können Sie bauen Flexibilität in den code ändern einige Attribute des singleton-Objekts jedes mal, wenn Sie führen Sie die Anwendung. Dies ist nicht eine Verletzung des Singleton-Musters. Es sieht aus wie eine Verletzung, wenn Sie sehen, aus code Perspektive.
Design Patterns sind da, um uns zu helfen, schreiben Sie eine flexible und erweiterbare code -, nicht zu hindern, uns zu schreiben guten code.
InformationsquelleAutor der Antwort Vinod Nalla
Wenn Sie wollen erstellen einer Singleton-Klasse dient als ein Rahmen, ein guter Weg ist, um eine Konfiguration-Datei, und Lesen der Parameter aus der Datei im Beispiel().
Wenn die Parameter der Fütterung der Singleton-Klasse werden dynamisch während der Ausführung des Programms, verwenden Sie einfach eine statische HashMap speichern von verschiedenen Instanzen der Singleton-Klasse, um sicherzustellen, dass für jeden parameter(s), nur eine Instanz erstellt wird.
InformationsquelleAutor der Antwort user3025839
Dies ist nicht ganz ein singleton, aber kann etwas sein, das könnte dein problem lösen.
InformationsquelleAutor der Antwort Kamilski81
Könnten wir nicht etwas wie das hier tun:
InformationsquelleAutor der Antwort Ionut Negru
Trotz allem, was einige vielleicht behaupten, hier ist ein singleton mit Parametern im Konstruktor
Dem singleton-Muster zu sagen :
respektiert mit diesem Beispiel.
Warum nicht direkt die Eigenschaft ? Es ist lehrbuch-Fall um zu zeigen, wie wir bekommen können ein singleton mit Konstruktor mit parameter, aber es könnte in manchen Situationen nützlich sein. Zum Beispiel in Erbschafts-Fällen zu zwingen, die singleton, um einige Oberklasse Eigenschaften.
InformationsquelleAutor der Antwort Zou
Singleton ist, natürlich, ein "anti-pattern" (vorausgesetzt, eine definition für eine statische variable state).
Wenn Sie wollen, einen festen Satz von unveränderlichen Wert Objekte, dann enums sind der Weg zu gehen. Für eine große, möglicherweise offene Menge der Werte, die Sie verwenden können, ein Repository in irgendeiner form - in der Regel basierend auf einer
Map
Umsetzung. Natürlich, wenn Sie sind den Umgang mit Statik seien Sie vorsichtig mit Gewinde (entweder synchronisieren ausreichend weit oder verwenden Sie eineConcurrentMap
entweder die Prüfung, dass ein anderer thread hat nicht geschlagen oder Sie verwenden irgendeine form von futures).InformationsquelleAutor der Antwort Tom Hawtin - tackline
Ich denke das ist ein Allgemeines problem. Die Trennung der "Initialisierung" des singleton aus dem "Holen" des singleton funktionieren könnte (in diesem Beispiel verwendet eine Variante des double-checked locking).
InformationsquelleAutor der Antwort Michael Andrews
Singletons sind in der Regel als anti-patterns und sollte nicht verwendet werden. Sie nicht den code einfach zu testen.
Singleton mit einem argument macht keinen Sinn, aber trotzdem - was würde passieren, wenn Sie schrieb:
Singleton ist auch nicht thread-safe als mehrere threads können gleichzeitig Anrufe zu
getInstance
die in mehr als eine Instanz erstellt wird (eventuell mit verschiedenen Werten vonx
).InformationsquelleAutor der Antwort oxbow_lakes