La réponse ci-dessous est fausse, mais je la garderai pour que les autres puissent en tirer des leçons (voir ci-dessous)
Dans ExampleA
, vous pouvez utiliser la même Config
instance sur plusieurs classes. Cependant, s'il ne doit y avoir qu'une seule Config
instance dans toute l'application, envisagez d'appliquer le modèle Singleton Config
pour éviter d'avoir plusieurs instances de Config
. Et si Config
c'est un Singleton, vous pouvez faire ce qui suit à la place:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
Dans ExampleB
, d'autre part, vous obtiendrez toujours une instance distincte de Config
pour chaque instance de ExampleB
.
La version à appliquer dépend vraiment de la manière dont l'application traitera les instances de Config
:
- si chaque instance de
ExampleX
doit avoir une instance distincte de Config
, allez avec ExampleB
;
- si chaque instance de
ExampleX
partage une (et une seule) instance de Config
, utilisez ExampleA with Config Singleton
;
- si les instances de
ExampleX
peuvent utiliser différentes instances de Config
, respectez ExampleA
.
Pourquoi se convertir Config
en Singleton est faux:
Je dois admettre que je n'ai appris le modèle Singleton qu'hier (en lisant le livre Head First sur les modèles de conception). Naïvement, je me suis déplacé et l'ai appliqué à cet exemple, mais comme beaucoup l'ont souligné, une manière est une autre (certains ont été plus cryptiques et ont seulement dit "vous vous trompez!"), Ce n'est pas une bonne idée. Donc, pour empêcher les autres de faire la même erreur que je viens de faire, voici un résumé des raisons pour lesquelles le modèle Singleton peut être nocif (sur la base des commentaires et de ce que j'ai découvert sur Google):
Si ExampleA
récupère sa propre référence à l' Config
instance, les classes seront étroitement couplées. Il n'y aura aucun moyen d'avoir une instance de ExampleA
pour utiliser une version différente de Config
(par exemple une sous-classe). C'est horrible si vous voulez tester en ExampleA
utilisant une instance de maquette Config
car il n'y a aucun moyen de le fournir ExampleA
.
La prémisse de qu'il y en aura une, et une seule, Config
peut - être maintenant , mais vous ne pouvez pas toujours être sûr que la même chose se reproduira à l'avenir . Si à un moment ultérieur, il s'avère que plusieurs instances de Config
seront souhaitables, il n'y a aucun moyen d'y parvenir sans réécrire le code.
Même si l'instance une et une seule de Config
est peut-être vraie pour toute l'éternité, il peut arriver que vous souhaitiez pouvoir utiliser une sous-classe de Config
(tout en n'ayant qu'une seule instance). Mais, puisque le code obtient directement l'instance via getInstance()
of Config
, qui est une static
méthode, il n'y a aucun moyen d'obtenir la sous-classe. Encore une fois, le code doit être réécrit.
Le fait que les ExampleA
utilisations Config
soient masquées, du moins lors de la simple visualisation de l'API de ExampleA
. Cela peut ou non être une mauvaise chose, mais personnellement, je pense que cela ressemble à un inconvénient; par exemple, lors de la maintenance, il n'y a pas de moyen simple de savoir à quelles classes seront affectées les modifications Config
sans examiner la mise en œuvre de toutes les autres classes.
Même si le fait d' ExampleA
utiliser un Singleton Config
n'est pas un problème en soi, il peut quand même devenir un problème du point de vue des tests. Les objets singleton porteront un état qui persistera jusqu'à la fin de l'application. Cela peut être un problème lors de l'exécution de tests unitaires car vous voulez qu'un test soit isolé d'un autre (c'est-à-dire que l'exécution d'un test ne devrait pas affecter le résultat d'un autre). Pour résoudre ce problème, l' objet Singleton doit être détruit entre chaque exécution de test (devant potentiellement redémarrer l'application entière), ce qui peut prendre du temps (sans parler de fastidieux et ennuyeux).
Cela dit, je suis heureux d'avoir fait cette erreur ici et non dans la mise en œuvre d'une véritable application. En fait, j'envisageais de réécrire mon dernier code pour utiliser le modèle Singleton pour certaines classes. Bien que j'aurais pu facilement annuler les modifications (tout est stocké dans un SVN, bien sûr), j'aurais quand même perdu du temps à le faire.