La risposta qui sotto è sbagliata, ma terrò per gli altri imparare da essa (vedi sotto)
In ExampleA
, è possibile utilizzare la stessa Config
istanza in più classi. Tuttavia, se ci dovrebbe essere solo Config
un'istanza all'interno dell'intera applicazione, prendere in considerazione l'applicazione del modello Singleton Config
per evitare di avere più istanze di Config
. E se Config
è un Singleton, puoi invece fare quanto segue:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
D' ExampleB
altra parte, otterrai sempre un'istanza separata di Config
per ogni istanza di ExampleB
.
La versione che dovresti applicare dipende davvero da come l'applicazione gestirà le istanze di Config
:
- se ogni istanza di
ExampleX
dovrebbe avere un'istanza separata di Config
, andare con ExampleB
;
- se ogni istanza di
ExampleX
condividerà una (e una sola) istanza di Config
, utilizzare ExampleA with Config Singleton
;
- se le istanze di
ExampleX
possono usare istanze diverse di Config
, attenersi a ExampleA
.
Perché la conversione Config
in Singleton è errata:
Devo ammettere che ieri ho imparato a conoscere il modello Singleton (leggendo il primo libro dei modelli di design di Head ). Ingenuamente sono andato in giro e l'ho applicato per questo esempio, ma come molti hanno sottolineato, in un modo sono un altro (alcuni sono stati più criptici e hanno detto solo "Stai sbagliando!"), Questa non è una buona idea. Quindi, per impedire ad altri di fare lo stesso errore che ho appena fatto, ecco un riassunto del motivo per cui il modello Singleton può essere dannoso (basato sui commenti e su ciò che ho scoperto cercandolo su Google):
Se ExampleA
recupera il proprio riferimento Config
all'istanza, le classi saranno strettamente accoppiate. Non ci sarà modo di avere un'istanza ExampleA
per usare una versione diversa di Config
(diciamo una sottoclasse). Questo è orribile se vuoi testare ExampleA
usando un'istanza di mock-up in Config
quanto non c'è modo di fornirlo ExampleA
.
La premessa di ci sarà una, e una sola, istanza di Config
forse vale ora , ma non si può sempre essere sicuri che lo stesso accadrà in futuro . Se in un momento successivo risulta che Config
saranno desiderabili più istanze di , non è possibile raggiungere questo obiettivo senza riscrivere il codice.
Anche se la sola e unica istanza di Config
è forse vera per tutta l'eternità, potrebbe accadere che tu voglia poter usare una sottoclasse di Config
(pur avendo ancora una sola istanza). Tuttavia, poiché il codice ottiene direttamente l'istanza tramite getInstance()
of Config
, che è un static
metodo, non è possibile ottenere la sottoclasse. Ancora una volta, il codice deve essere riscritto.
Il fatto che ExampleA
usi Config
sarà nascosto, almeno quando si visualizza semplicemente l'API di ExampleA
. Questa può essere o meno una brutta cosa, ma personalmente ritengo che ciò sembri uno svantaggio; ad esempio, quando lo si mantiene, non esiste un modo semplice per scoprire a quali classi saranno interessate le modifiche Config
senza esaminare l'implementazione di ogni altra classe.
Anche se il fatto che ExampleA
utilizza un Singleton Config
non è un problema in sé, può comunque diventare un problema dal punto di vista del test. Gli oggetti Singleton avranno uno stato che persisterà fino al termine dell'applicazione. Questo può essere un problema quando si eseguono unit test in quanto si desidera che un test sia isolato da un altro (vale a dire che aver eseguito un test non dovrebbe influire sul risultato di un altro). Per risolvere questo problema, l' oggetto Singleton deve essere distrutto tra ogni esecuzione di test (potrebbe essere necessario riavviare l'intera applicazione), il che può richiedere molto tempo (per non dire noioso e fastidioso).
Detto questo, sono contento di aver fatto questo errore qui e non nell'implementazione di una vera applicazione. In effetti, stavo davvero considerando di riscrivere il mio ultimo codice per utilizzare il modello Singleton per alcune delle classi. Anche se avrei potuto facilmente ripristinare le modifiche (tutto è archiviato in un SVN, ovviamente), avrei comunque perso tempo a farlo.