2010-12-28 6 views
1

Ich habe mit einer interessanten Idee gespielt (Keine Ahnung, ob ich es in einen Code aufnehmen werde, aber es macht Spaß darüber nachzudenken)sind hierarchische Singletons in Java möglich?

Nehmen wir an, wir haben ein Programm, das eine große Anzahl von Klassen erfordert einer bestimmten Unterklasse. Und diese Klassen müssen alle Singletons sein. Nun könnten wir das Singleton-Muster für jede dieser Klassen schreiben, aber es erscheint verschwenderisch, den gleichen Code immer wieder zu schreiben, und wir haben bereits eine gemeinsame Basisklasse. Es wäre wirklich schön, ein getSingleton Methode von A zu schaffen, die, wenn sie von einer Unterklasse genannt, ein Singleton der B-Klasse gibt (Guss der Klasse A der Einfachheit halber)

class A{ 
    public A getSingleton(){ 
     //Wizardry 
    } 
} 
class B extends A{ 
} 

A blargh = B.getSingleton() 
A gish = B.getSingleton() 
if(A == B) 
    System.out.println("It works!") 

Es scheint mir, dass die Art und Weise zu tun Das wäre, Bs Standardkonstruktor zu erkennen und aufzurufen (vorausgesetzt, wir müssen nichts weiterreichen.) Ich kenne ein wenig von der schwarzen Magie der Reflektion in Java, aber ich bin mir nicht sicher, ob das möglich ist.

Wer interessiert sich dafür zu rätseln?

+0

Sie brauchen selten ein echtes Singleton. In einigen Apps benötigen Sie möglicherweise Objekte, die während des Lebenszyklus Ihrer Anwendung genau eine Instanz haben sollen. Aber Sie sollten wahrscheinlich * kein * Singleton dafür verwenden, weil es korrekte Einheitentests verkomplizieren (oder verhindern) soll. Was Sie wollen, ist etwas, das fast ein Singleton ist, aber nicht genau. Framework wie Spring kann in solchen Fällen helfen. – SyntaxT3rr0r

+0

@Chris S. - Wie unterscheidet sich Ihr Kommentar von meiner Antwort? Wir schlagen beide vor, dass Singletons nicht die Antwort sind. Warum sagst du, dass ich "nicht helfe"? – duffymo

Antwort

2

Technisch sehe ich keinen Grund, warum etwas ähnliches nicht getan werden kann. Ihr genaues Schema funktioniert nicht, weil Ihr getSingletonstatic ist (obwohl Sie es nicht als solches deklarieren), so dass es nicht sagen kann, für welche Klasse es aufgerufen wird. Ändern Sie es in static A getSingleton(Class cls), und es könnte funktionieren.

Aber ist das wirklich ein großer Gewinn gegenüber einem Einzeiler getSingleton in jeder abgeleiteten Klasse?

Für den Anfang Ihr ein getSingleton kehrt A, also wenn jemand es für B nennt, bekommen sie eine A zurück und müssen niedergeschlagenen es als B zu verwenden.

Auch das Schema ist nicht genau transparent.

Sicher, es macht Spaß darüber nachzudenken, aber ich würde nach zwingenden Gründen suchen, bevor ich dies in einem Produktionssystem mache.

0

Die Antwort ist "Nein", das ist nicht möglich.

Wenn Vererbung "IS-A" bedeutet, dann ist B ein A, und sie sind keine Singletons mehr.

„... große Anzahl von Klassen, die alle eine bestimmte Unterklasse. Und diese Klassen müssen alle Singletons sein ...“

ich gerade wieder lesen diese. Sind "große Zahl" und "Singleton" nicht widersprüchlich?

Persönlich möchte ich nicht so etwas beibehalten müssen. Ich denke, es ist ein Beispiel für eine Überbeanspruchung des Singleton-Musters, das nahe daran war, voted off the island at OOPSLA zu sein, und übertriebene Klugheit.

Google hat utilities geschrieben, um Singletons in ihrem Code zu identifizieren, damit sie entfernt werden können. Möchten Sie immer noch mit Ihnen Code schreiben?

+0

Hängt davon ab, wie wir dem Fragesteller helfen. Wenn Sie Code schreiben, um jemandem zu helfen, etwas zu tun, das nicht empfohlen wird, helfen Sie wirklich? Ich erzähle es lieber und werde erzählt. – duffymo

1

Sie können es auf diese Weise tun, um die Klasse angibt: (in der Tat kann man für alle Klassen verwenden, wenn sie öffentlich noargs Konstruktor)

//Code not tested 
class A { 
    private static ConcurrentHashMap<Class,Object> instances=new ConcurrentHashMap(); 

    private A(){} 

    public static <T> T getInstance(Class<T extends A> classe) { 
     Object instance=instances.get(classe); 
     if(instance==null) { 
     instance=createInstance(classe,instance); 
     } 
     return instance; 
    } 

    protected <T> T createInstance(Class<T> classe) { 
     return classe.getConstructor().newInstance(); 
    } 
} 
1

Es ist eine interessante Idee. Eine andere Möglichkeit, doppelten Code zu reduzieren, besteht darin, ein Tool zu verwenden, um die Erstellung Ihrer "Singleton" s zu verarbeiten.Eine gängige Methode hierfür in Java ist die Verwendung eines Dependency-Injection-Tools wie Spring, mit dem Sie alle Typen definieren können, die Singletons sein sollen, und diese Typen dann von Spring anfordern, wenn Sie sie benötigen. Spring stellt dann sicher, dass es immer nur einen von jedem angeforderten Typ erstellt. Es gibt fast keine Code-Duplizierung.

Dies hat den Vorteil, Singleton-Verhalten nicht auf den Typ selbst zu erzwingen. Viele der Probleme mit Singletons drehen sich darum, wie unglaublich schwer es ihnen gelingt, Code aufgrund ihres globalen Zustands effektiv zu testen (ich war an Projekten beteiligt, bei denen ich viel Zeit darauf verwendet habe, herauszufinden, wie Tests repariert werden können, weil zwei verschiedene Tests modifizieren einen Singleton). Mit Spring können Sie Singleton-ähnliches Verhalten erhalten, aber auch separate Instanzen der Typen erstellen, wenn dies sinnvoll ist.