Le variabili statiche vanno bene se usate per le costanti, che include costanti i cui valori sono calcolati in fase di esecuzione ma non dipendono da alcun input. Le variabili statiche potrebbero anche essere OK se vengono utilizzate solo all'interno di una classe.
Una volta che le variabili statiche diventano parte del flusso di dati esterno, potresti riscontrare una serie di problemi:
-
Ordine di inizializzazione tra più classi. Se non puoi garantire che questo campo sia inizializzato prima che la classe possa essere istanziata, potresti potenzialmente bloccare la tua applicazione. Ciò è particolarmente grave in C ++, dove seguiranno i segfault.
-
Testabilità. Con variabili statiche, non puoi testare un oggetto in isolamento. Devi pensare all'intero gruppo di oggetti che interagiscono con la variabile statica.
-
accoppiamento. Se il codice esterno interagisce con questa variabile statica, questo codice è strettamente accoppiato a quella classe. Ciò rende più difficile l'evoluzione della base di codice nel tempo.
-
correttezza. Se il codice esterno imposta la variabile, potrebbero dare delle assurdità. La correttezza della classe ora dipende dalla correttezza di tutti i suoi clienti, il che è indesiderabile.
Riesco a vedere due soluzioni ragionevoli: inizializzazione pigra o istanziazione tramite factory.
Con l'inizializzazione pigra, il costruttore inizializza il valore, ma solo se è attualmente non inizializzato. Il modo in cui questo deve essere eseguito correttamente dipende dalla lingua, soprattutto se questa inizializzazione deve essere protetta da un errore. Se ricordo bene, la "danza di inizializzazione del pigro singleton" sarebbe simile a questa in Java:
private static volatile Thing variable;
Constructor() {
if (variable == null) {
synchronized(Constructor.class) {
if (variable == null)
variable = initializeVariable();
}
}
}
Ma non citarmi su di esso ...
Con una fabbrica, possiamo evitare completamente le variabili globali. Il valore inizializzato ora è memorizzato nell'oggetto factory e viene passato a ogni istanza creata come dipendenza nel costruttore. Qualsiasi codice che desideri creare un'istanza di oggetti della classe deve essere fornito in fabbrica. Il codice non dovrebbe creare ogni volta una nuova factory, perché ricalcolare il valore di nuovo.
private Thing variable;
private Constructor(Thing variable) {
this.variable = variable;
...
}
public static class Factory {
private final Thing variable;
Factory() {
variable = initializeVariable();
}
Constructor create() { return new Constructor(variable); }
}
In Java useremmo un% co_de nidificato, in C ++ probabilmente un public static class Factory
. Non conosco il linguaggio C # appropriato.
Se si sta utilizzando un framework di iniezione delle dipendenze, è probabile che si possa evitare di scrivere esplicitamente la factory. Invece, dichiareresti il costoso per calcolare il campo istanza e collegalo al tuo framework in modo che possa essere compilato automaticamente. Quindi, si crea una funzione che può fornire questa dipendenza. Il framework ha probabilmente qualche modalità singleton in modo che la funzione venga invocata una volta sola.