La risposta qui sotto è sbagliata, ma terrò che gli altri imparino da esso (vedi sotto)
In ExampleA
, puoi utilizzare la stessa istanza Config
su più classi. Tuttavia, se dovesse esserci solo un'istanza Config
nell'intera applicazione, considera l'applicazione del modello Singleton su Config
per evitare di avere più istanze di Config
. E se Config
è un Singleton, puoi fare invece quanto segue:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
In ExampleB
, d'altra parte, otterrai sempre un'istanza separata di Config
per ogni istanza di ExampleB
.
Quale versione devi applicare dipende da come l'applicazione gestirà le istanze di Config
:
- se ogni istanza di
ExampleX
deve avere un'istanza separata di Config
, vai con ExampleB
;
- se ogni istanza di
ExampleX
condividerà una (e solo una) istanza di Config
, usa ExampleA with Config Singleton
;
- se le istanze di
ExampleX
possono utilizzare diverse istanze di Config
, bastone con ExampleA
.
Perché la conversione di Config
in Singleton è errata:
Devo ammettere che ho appreso solo ieri del pattern Singleton (leggendo il libro Head First dei pattern design). Ingenuamente sono andato in giro e l'ho applicato per questo esempio, ma come molti hanno sottolineato, in un modo ce ne sono altri (alcuni sono stati più criptici e hanno detto solo "Stai sbagliando!"), Questa non è una buona idea. Quindi, per evitare che altri facciano lo stesso errore che ho appena fatto, ecco un riassunto del motivo per cui il pattern Singleton può essere dannoso (basato sui commenti e su quello che ho trovato su Google):
-
Se ExampleA
recupera il proprio riferimento all'istanza Config
, le classi saranno strettamente accoppiate. Non ci sarà modo di avere un'istanza di ExampleA
per utilizzare una versione diversa di Config
(ad esempio alcune sottoclassi). È orribile se vuoi testare ExampleA
usando un'istanza di simulazione di Config
poiché non c'è modo di fornirlo a ExampleA
.
-
La premessa di ci sarà una, e solo una, istanza di Config
forse contiene ora , ma non puoi sempre essere sicuro che lo stesso rimarrà nel futuro . Se in un secondo momento risultasse che sarebbero desiderabili più istanze di Config
, non c'è modo di ottenere ciò senza riscrivere il codice.
-
Anche se l'unica ed unica istanza di Config
è forse vera per l'eternità, potrebbe succedere che tu voglia utilizzare alcune sottoclassi di Config
(pur avendo ancora solo un esempio). Ma poiché il codice ottiene direttamente l'istanza tramite getInstance()
di Config
, che è un metodo static
, non c'è modo di ottenere la sottoclasse. Ancora una volta, il codice deve essere riscritto.
-
Il fatto che ExampleA
usi Config
sarà nascosto, almeno quando visualizzi solo l'API di ExampleA
. Questo può o non può essere una cosa negativa, ma personalmente ritengo che ciò sembri uno svantaggio; ad esempio, quando si mantiene, non esiste un modo semplice per scoprire quali classi saranno influenzate dalle modifiche a Config
senza esaminare l'implementazione di ogni altra classe.
-
Anche se il fatto che ExampleA
utilizzi un Singleton Config
non è un problema in sé, può ancora diventare un problema dal punto di vista del test. Gli oggetti Singleton porteranno in uno stato che durerà fino alla fine dell'applicazione. Questo può essere un problema quando si eseguono i test di unità in quanto si desidera isolare un test da un altro (ad esempio, l'esecuzione di un test non dovrebbe influire sul risultato di un altro). Per risolvere questo problema, l'oggetto Singleton deve essere distrutto tra ogni esecuzione di prova (potenzialmente dover riavviare l'intera applicazione), il che potrebbe richiedere molto tempo (per non dire noioso e noioso).
Detto questo, sono contento di aver fatto questo errore qui e non nell'implementazione di un'applicazione reale. In effetti, stavo davvero pensando di riscrivere il mio ultimo codice per usare il pattern Singleton per alcune delle classi. Anche se potrei facilmente ripristinare le modifiche (ovviamente tutto è memorizzato in un SVN), avrei comunque perso tempo a farlo.