[PHP] Comprendre le design pattern Factory

Le patron de conception la Fabrique (factory) est un patron de conception de création souvent utilisé en programmation orientée objet.

Le but de ce patron est de retourné une instance d’une classe parmi plusieurs possibles, en fonction des paramètres qui ont été fournis.

Par exemple, nous allons développer une bibliothèque qui parse un fichier est retourne les données y contenue dans un tableau (Array), ce fichier peut être de type : json, xml ou yaml.

La solution sera de créer une classe pour chaque type de fichier, chaque classe est composée de deux methodes : read et parse.

La première étape consiste à créer une interface qui définis ces deux méthodes :

interface ParserInterface {

    /**
     * Read file content
     */
    public function readFile();

    /**
     * Parse file content
     */
    public function parseFile();
}

Par la suite nous définissons nos classes qui vont implémenter cet interface :

class JsonParser implements ParserInterface {

    public $content;

    public function __construct($file) {
        $this->readFile($file);
    }

    public function readFile($file) {
        if (file_exists($file)) {
            $this->content = file_get_contents($file);
        }
    }

    public function parseFile() {
        return json_decode($this->content);
    }
}
class YamlParser implements ParserInterface {

    public $content;

    public function __construct($file) {
        $this->readFile($file);
    }

    public function readFile($file) {
        if (file_exists($file)) {
            $this->content = file_get_contents($file);
        }
    }

    public function parseFile() {
        return yaml_parse($this->content);
    }

}
class XmlParser implements ParserInterface {

    public $content;

    public function __construct($file) {
        $this->readFile($file);
    }

    public function readFile($file) {
        if (file_exists($file)) {
            $this->content = file_get_contents($file);
        }
    }

    public function parseFile() {
        return simplexml_load_string($this->content);
    }

}

Pour utiliser cette bibliothèque, il faut à chaque fois tester sur le type de fichier est initialisé la classe correspondante, le code rassemblera à celui la :

$file = __DIR__ . "/file.json";

switch (pathinfo($file, PATHINFO_EXTENSION)) {
    case "json":
        $obj = new JsonParser($file);
        break;
    case "xml":
        $obj = new XmlParser($file);
        break;
    case "yml":
        $obj = new YamlParser($file);
        break;
    default:
        throw new Exception("File type unsupported");
}

var_dump($obj->parseFile());

À chaque fois que nous allons utiliser notre bibliothèque, nous aurons besoin de ré-écrire ce code, si un jour nous ajoutons un nouveau parseur, nous aurons besoin de faire un tour dans les fichiers et modifier cette partie.

Pour avoir une seule endroit ou initialiser notre parseur, nous faisons appel au patron fabrique qui sera le seule responsable de la création / distribution de l’objet, ainsi nous pouvons modifier/ajouter des nouveaux parseur sans se soucier.

Notre classe Factory sera une simple class PHP, contenant une méthode abstraite qui se charge de l’initialisation des objets, elle sera définis comme suit :

class ParserFactory {

    public static function getParser($file) {

        switch (pathinfo($file, PATHINFO_EXTENSION)) {
            case "json":
                return new JsonParser($file);
            case "xml":
                return new XmlParser($file);
            case "yml":
                return new YamlParser($file);
            default:
                throw new Exception("File type unsupported");
        }
    }
}

Par la suite, à chaque fois que nous voulons parser un fichier, nous appelons notre méthode statique :

$file = __DIR__ . "/file.json";

$obj = ParserFactory::getParser($file);

var_dump($obj->parseFile());

Vous pouvez consulter le code source de cet exemple en suivant ce lien