2009-07-14 10 views
5

Voglio istanziare un'istanza di una classe dalla stringa nome della classe. (.. Usando Class.forName() newInstance())Istanziare l'oggetto singleton utilizzando Class.forName()?

Ecco il problema: voglio che sia un esempio per Singleton .. Potrei farlo utilizzando un pattern Singleton, se non che newInstance chiama il costruttore predefinito per una classe, e con un singleton, quel costruttore deve essere "privato" ..

Esiste una soluzione? Potrei pensare ad un modo meno elegante per fare questo (utilizzando una HashMap come una tabella di ricerca ..), ma preferirei una soluzione migliore ..

Grazie,

+0

Ho appena letto la tua domanda due volte e non la seguo ... Forse altri lo faranno ma ho pensato di farti sapere ... –

+2

Perché ne hai bisogno in quel modo? – akarnokd

+0

FYI: http: //developers.sun.com/learning/javaoneonline/2008/pdf/TS-6623.pdf pagina 31. – akarnokd

risposta

1

Si potrebbe usare un enum e hanno una HashMap chiamata per ognuno di essi. Oppure si potrebbe usare un quadro di riferimento iniezione di dipendenza per ottenere un singoletto di qualcosa (? Guice)

Modifica Va bene, io salto in con un esempio di codice troppo:

package tests; 
public class EnumSingleton { 
    public static void main(String[] args) throws Exception { 
     Class<?> c = Class.forName("tests.Singleton1"); 
     Operation instance = Operation.class.cast(c.getEnumConstants()[0]); 
     System.out.println(instance.getTHEAnswer()); 

     c = Class.forName("tests.Singleton2"); 
     instance = Operation.class.cast(c.getEnumConstants()[0]); 
     System.out.println(instance.getTHEAnswer()); 
    } 
} 
interface Operation { 
    int getTHEAnswer(); 
} 
enum Singleton1 implements Operation { 
    INSTANCE; 
    @Override 
    public int getTHEAnswer() { 
     return 42; 
    } 
} 
enum Singleton2 implements Operation { 
    INSTANCE; 
    @Override 
    public int getTHEAnswer() { 
     return 84; 
    } 
} 

e il suo suono e sicura. Modifica E ha un significato ora.

8

Un singleton classico ha anche un metodo getInstance() statico: lo chiamiamo tramite reflection anziché usando newInstance(). Sì, è più lavoro, ma è così che funziona ...

Oppure puoi usare lo setAccessible() per chiamare comunque il costruttore privato, ma rompi il singleton e vai all'inferno.

In terzo luogo, si potrebbe evitare di avere un Singleton del tutto e trovare una soluzione migliore (di solito c'è).

+0

s/solito/sempre/ –

7

È possibile utilizzare la riflessione per ottenere un riferimento a un metodo factory statico della classe, quindi richiamarlo. Il metodo di fabbrica potrebbe far rispettare il pattern Singleton

Class c = Class.forName("test.MyClass"); 
Method factoryMethod = c.getDeclaredMethod("getInstance"); 
Object singleton = factoryMethod.invoke(null, null); 

E poi

public class MyClass { 

    private static MyClass instance; 

    private MyClass() { 
     // private c'tor 
    } 

    public static synchronized MyClass getInstance() { 
     if (instance == null) { 
     instance = new MyClass(); 
     } 
     return instance: 
    } 
} 

Attenzione: Singleton design pattern può essere dannoso per la salute a lungo termine.

+0

Bello, vorrei ancora sapere perché l'OP vuole avere un singleton per nome? – akarnokd

+0

Forse stanno reinventando la primavera. – skaffman

+0

Lotto di piccoli singleton! –

2

Dovrai conoscere il nome del metodo della classe singleton che costruisce l'oggetto. Se è per es. chiamato "instance()" si può fare qualcosa come

Class c = Class.forName("MySingleton"); 
Method m = c.getDeclaredMethod("instance",null); 
MySingleton singleton = m.invoke(null,null); 
0

Si può fare affidamento sull'esistenza di un metodo di fabbrica statico? Si baserebbe su qualche modo di convenzione sui nomi, ma funzionerebbe.

In conclusione: se una classe deve essere nota per essere singleton, deve avere la responsabilità di tale controllo. Quindi deve essere conforme ad alcune implementazioni del pattern, e se si desidera una selezione dinamica tra tali classi, è necessario essere in grado di prevedere l'approccio "Factory".