Un'implementazione di pattern singleton come:
public final class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
può essere sostituito con un'iniezione di dipendenza. Costruisci semplicemente l'oggetto una volta, nel metodo statico main
, e passa a tutto ciò che ne ha bisogno.
public static void main(){
Date applicationStart = new Date();
Uptime uptime = new Uptime(applicationStart);
Performance performance = new Performance(applicationStart);
//...
}
Qui due oggetti che entrambi hanno bisogno di sapere che l'applicazione si avvia e non vogliono vedere la Data costruita due volte hanno entrambi riferimenti allo stesso singolo oggetto. Passando responsabilmente intorno a un riferimento piuttosto che spaventosamente impedendo la costruzione, tutti i requisiti sono soddisfatti. Questo approccio consente una maggiore flessibilità poiché gli utenti del singleton non sono tenuti a sapere come trovarlo.
Lo svantaggio di questo approccio è che non supporta l'inizializzazione pigra. Quale potrebbe essere fatto con:
public final class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Tuttavia, questo è necessario solo se la costruzione dell'oggetto è costosa. Molti progetti evitano il problema proibendo ai costruttori di svolgere attività oltre alla convalida e all'archiviazione di variabili di istanza. Generalmente nessuno dei due è abbastanza costoso da giustificare un'inizializzazione pigra. La dimensione dell'oggetto può anche essere un motivo per l'inizializzazione pigra. I buoni design tendono ad evitare oggetti di grandi dimensioni. L'inizializzazione di una risorsa e la modellazione della sua disponibilità con la creazione di un oggetto possono anche fornire un motivo per utilizzare l'inizializzazione pigra. Quanto senso può avere dipende dal linguaggio dovuto alla semantica della vita dell'oggetto.
L'inizializzazione pigra non richiede in ogni caso il modello singleton. DI combinato con un singolo oggetto factory astratto che memorizza nella cache anche l'oggetto che costruisce quando chiamato soddisferà anche un pigro requisito di inizializzazione senza i client hard coding al codice di costruzione.
Il modello singleton è in gran parte evitato perché risolve i problemi che i buoni progetti non hanno in primo luogo. Ma quando sorge la necessità funziona ancora bene come ha sempre fatto. Orientato agli oggetti o no.