Questa domanda è correlata ad Android ma può anche essere richiesta in altre situazioni. Ho bisogno di creare una biblioteca dove sono esposti i singleton; o voglio assicurarmi che esista solo una istanza delle mie classi e che possa essere afferrata ovunque nel codice senza passare dei riferimenti.Come implementare un singleton configurabile?
Ma questi singleton hanno bisogno di alcuni parametri. Ad esempio in Android, è spesso necessario un oggetto Context
. Devo anche precisare che, dal momento che fornisco una libreria, voglio che le cose siano facili per l'utente e Non ho il controllo della classe Application
in Android (questa classe può talvolta essere utilizzata per gestire le istanze dell'oggetto per un'intera app) .
Una soluzione nota è quella di effettuare le seguenti operazioni:
static MySingleton sInstance;
MySingleton.getInstance(Context c) {
if (sInstance == null) {
sInstance = new MySingleton(c.getApplicationContext());
}
return sInstance;
}
Ma è strano dato che il parametro di getInstance
è effettivamente utilizzato solo alla prima creazione del Singleton.
Potrei fornire un setter per il singleton e chiede agli sviluppatori di impostare correttamente i parametri necessari, ma potrebbero sorgere alcune situazioni strane:
// Good usage
MySingleton.getInstance().setContext(context.getApplicationContext());
MySingleton.getInstance().doSomethingThatRequiresContext(); // OK
// Bad usage
MySingleton.getInstance().doSomethingThatRequiresContext(); // Error!
MySingleton.getInstance().setContext(context.getApplicationContext());
ho potuto verificare all'inizio di ciascun metodo se il Singleton è configurati correttamente e lanciare alcune eccezioni in caso di cattivo stato, ma l'API è meno semplice da usare:
MySingleton.getInstance().setContext(context.getApplicationContext());
try {
MySingleton.getInstance().doSomethingThatRequiresContext();
}
catch(BadSingletonConfiguration e) { }
Anche se io uso le eccezioni di runtime, sarebbe pericoloso per l'uso.
A meno che non chieda gentilmente all'utente di creare manualmente l'istanza e assicurarsi che solo un'istanza esisterà, non vedo una buona soluzione.
magari utilizzare oggetti immutabili .... Java String viene implementato per essere immutabile. – JFPicard
Si noti che ognuno dei seguenti esempi presenta una perdita di memoria se il singleton viene fatto riferimento all'interno di un thread. Devi usare WeakReference per memorizzare un contesto, altrimenti il contesto non sarà GC quando dovrebbe essere altrimenti. – mawalker
Se si scrive sul contesto, di solito viene eseguito un getApplicationContext() per avere un contesto che comprenda l'intero ciclo di vita dell'attività, quindi non viene eseguito GC mentre l'app è in diretta. Posso modificare gli esempi, se ti va. –