Je réfléchis à l'une des deux manières différentes d'implémenter le patron d'usine en PHP. Je ne sais pas si ces variantes ont des noms propres donc pour l'instant je vais les appeler usine interne et usine externe.Usine interne ou externe
usine interne: La méthode de fabrication est mis en œuvre dans la classe comme une méthode publique statique
<?php
class Foo
{
protected
$loadedProps = false;
public static factory ($id)
{
$class = get_called_class();
$item = new $class ($id);
if ($item -> loadedProps())
{
return ($item);
}
}
public function loadedProps()
{
return ($this -> loadedProps);
}
protected function loadPropsFromDB ($id)
{
// Some SQL logic goes here
}
protected function __construct ($id)
{
$this -> loadedProps = $this -> loadPropsFromDB ($id);
}
}
?>
usine externe: L'usine et les éléments initialise sont mis en œuvre comme des entités distinctes
<?php
class Foo
{
protected
$loadedProps = false;
public function loadedProps()
{
return ($this -> loadedProps);
}
protected function loadPropsFromDB ($id)
{
// Some SQL logic goes here
}
public function __construct ($id)
{
$this -> loadedProps = $this -> loadPropsFromDB ($id);
}
}
abstract class FooFactory
{
public static factory ($id)
{
$item = new Foo ($id);
if ($item -> loadedProps())
{
return ($item);
}
}
}
?>
Maintenant, il me semble que chacun a ses mérites.
Le premier vous permet de cacher le constructeur du monde extérieur. Cela signifie que la seule façon de créer un objet Foo est via l'usine. Si l'état de l'élément ne peut pas être chargé à partir de la base de données, l'usine renverra la valeur NULL que vous pouvez vérifier facilement dans le code.
if ($item = Foo::factory ($id))
{
// ...
}
else
{
// The item failed to load. Handle error here
}
La fabrique peut également créer des objets de n'importe quelle sous-classe de Foo sans aucune modification.
Cependant, il semble avoir quelques inconvénients. Tout d'abord, la classe doit mettre en place l'usine, ce qui pourrait mettre des responsabilités dans la classe qui appartient vraiment ailleurs. La version interne de l'usine donne certainement une classe plus grande que la version externe de l'usine. En ce qui concerne l'usine externe, c'est plus propre car l'usine n'est pas dans la classe elle-même et je n'ai pas à m'inquiéter d'une classe prenant plus de responsabilités qu'elle ne le devrait. L'usine externe peut également être mieux adaptée à l'injection de dépendance.
Cependant, il a son propre ensemble d'inconvénients. Tout d'abord, le constructeur de l'objet à construire en usine doit être public car PHP n'a pas de concept de package et pas de niveau de protection 'package' pour les membres de la classe. Cela signifie que rien n'empêche un codeur de simplement faire un nouveau Foo() et de contourner l'usine (cela peut cependant faciliter les tests unitaires).
L'autre problème est que FooFactory ne peut créer que des objets Foo, et non aucune de ses sous-classes. Cela pourrait être contourné en ajoutant un autre paramètre à la FooFactory pour spécifier un nom de classe, mais alors l'usine devra faire des vérifications internes que la classe d'objet spécifiée est en fait un descendant de Foo.
Donc, fondamentalement, quels sont les mérites relatifs des deux approches, et que recommanderiez-vous?
En outre, s'ils ont des noms plus propres que l'usine interne ou externe, j'aimerais les connaître.
'Hors sujet:' Sur une note aléatoire, je trouve amusant que vous parliez tous les deux de la même chose lorsque vous avez le même nom d'utilisateur. Pendant une seconde, j'ai cru que tu te parlais à toi-même. – Tek
@Tek oui, Gordon répondant à Gordon. Mais je suis Gordon ™ :) – Gordon