Logo classes.scriptsphp.org PHP

go to nav bar

Le design pattern Factory :: Méthode de factorisation

Date :: 2004-12-19
Last Updated :: 2004-12-22


Introduction

Dans cet article, nous allons étudier le design pattern factory et plus précisemment la méthode de factorisation (The factory method). Le but de cette méthode est de déleguer certains traitements à d'autres classes, en instanciant les objets correspondants selon le contexte, ce qui permet d'avoir du code beaucoup plus maintenable, évolutif et réutilisable dans le cadre de projets assez volumineux.

Il existe différentes manières d'utiliser la méthode de factorisation, nous prendrons comme exemple, les news d'un site. Nous les résumerons à un titre et un contenu et nous allons voir comment, à partir d'une classe news, factoriser l'accès aux données et la génération du code de sortie.


Factorisation de l'accès aux données

Créons donc 3 classes :

  • news : la classe qui va être factorisée, elle contient les méthodes publiques qui seront utilisées pour la récupération de nos informations (titre et contenu) :
    • news::title() : renvoie le titre,
    • news::content() : renvoie le contenu.
  • _factory : Classe abstraite contenant la méthode de factorisation :
    • _factory::getNews() : Méthode de factorisation, elle renvoie une instance de la classe news.
  • newsFromArray : la classe qui va récupérer nos news à partir d'un tableau declaré dans le constructeur (pour l'exemple) , elle étend les fonctionnailités de la classe _factory :
    • newsFromArray::__construct() : Constructeur de la classe où l'on doit créer le tableau à exploiter dans la méthode de factorisation.

Code

<?php 


class news {
    private 
$title;
    private 
$content;

    public function 
__construct($data) {
        
$this->title $data['title'];
        
$this->content $data['content'];
    }

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


abstract class 
_factory {
    private 
$key 0;
    
// Méthode de factorisation
    
public function getNews() {
        if(isset(
$this->news[$this->key])) {
            return new 
news($this->news[$this->key++]);
        } else {
            
$this->key 0;
            return 
false;
        }
    }
}


class 
newsFromArray extends _factory {
    
    protected 
$news = array();

    public function 
__construct() {
        
$this->news[] = array('title'=>'cool''content'=>'ma news1');
        
$this->news[] = array('title'=>'slurp','content'=>'ma news2');
    }    

}


?>

Utilisation

Nous allons donc instancier la classe newsFromArray et afficher nos news grâce à la méthode de factorisation :

<?php 

$N 
= new newsFromArray;

while( 
$news $N->getNews() ) {
    echo 
'<h2>' $news->title() , '</h2>';
    echo 
'<p>' $news->content() , '</p>';
}

?>

Démonstration de la factorisation

Supposons désormais que nous avons affaire à un gestionnaire multi-news, et que les données de ces news proviennent d'origines diverses, comme par exemple une base de données pour les news locales, un service web pour d'autres, ou encore un fichier XML :

Le fichier XML

Prenons donc l'exemple où nos news sont stockées dans un fichier XML (ce fichier peut très bien être situé sur un serveur distant) :

<?xml version="1.0" encoding="iso-8859-1" ?>
<root>
    <item>
        <title>cool</title>
        <content>ma news 1</content>
    </item>
    <item>
        <title>slurp</title>
        <content>ma news 2</content>
    </item>
</root>

Récupérons nos données à partir de ce fichier XML

Nous allons donc créer une classe newsFromXML à cet effet, qui remplira le même rôle que la classe newsfromArray, mais en récupérant les données contenues dans notre fichier XML :

<?php 
class newsFromXML extends _factory {
    
    protected 
$news = array();

    public function 
__construct($XMLFile) {
        
$X simplexml_load_file($XMLFile);
        foreach(
$X as $c) {
            
$this->news[] = array('title'=>$c->title'content'=>$c->content);
        }
    }    

}
?>

Utilisation

Nous allons générer notre code HTML, à partir du fichier XML :

<?php 

$XML 
'http://site.com/news.xml';

$N = new newsFromXML($XML);

while( 
$news $N->getNews() ) {
    echo 
'<h2>' $news->title() , '</h2>';
    echo 
'<p>' $news->content() , '</p>';
}

?>

Nous aurions pu également charger ces informations à partir d'une base de données, d'un service web, etc. L' utilisation ne diffère pas, la classe news a été factorisée.

Allons plus loin ....

Nous allons voir un autre exemple de la méthode de factorisation. Sur la base précédente, nous allons créer 3 classes supplémentaires afin d'obtenir un code de sortie différent (HTML ou RSS) selon le contexte :

  • toHTML : classe de rendu HTML de nos news,
  • toRSS : classe de rendu RSS de nos news,
  • renderer : factorisation des deux classes précédentes.

Rendu HTML

Sur la base de l'exemple précédent, nous allons donc créer une classe pour générer du code HTML, ainsi, il sera aisément possible, grâce à la factorisation, de remplacer cette classe pour, par exemple, générer du RSS, comme dans l'exemple suivant, voire du PDF, etc, et ce, toujours sans avoir à retoucher à notre classe news.

<?php 

class toHTML {
    function 
__construct($newsObject) {
        
$this->$newsObject;
    }
    function 
display() {
        
$return '';
        while( 
$news $this->N->getNews() ) {
            
$return .= '<h2>' $news->title() . '</h2>';
            
$return .= '<p>' $news->content() . '</p>';
        }
        return 
$return;
    }
}

?>

Rendu RSS

Sur le même principe, générons les balises <item> d'un fichier RSS :

<?php 

class toRSS {
    function 
__construct($newsObject) {
        
$this->$newsObject;
    }
    function 
display() {
        
$return '';
        while( 
$news $this->N->getNews() ) {
            
$return .= '<item>';
            
$return .= '<title>' $news->title() . '</title>';
            
$return .= '<description>' $news->content() . '</description>';
            
$return .= '</item>';
        }
        return 
$return;
    }
}

?>

Factorisation des classes de rendu

Nous allons créer une classe renderer contenant une méthode de factorisation, renderer::create(), qui sera chargée de renvoyer une instance de la classe toHTML ou toRSS, selon le contexte.

<?php 

class renderer {
    function 
create($dataObject $type) {
        
        switch(
strtolower($type)) {
            case 
'html' :
            return new 
toHTML($dataObject);
            break;
            case 
'rss' :
            return new 
toRSS($dataObject);
            break;
        }
    }
}

?>

Exemples concrets

Ici, nous chargeons les données à partir de notre fichier XML, et générons du HTML en sortie.

<?php 

$N 
= new newsFromXML($XML);

$H renderer::create($N'HTML');
echo 
$H->display();

?>

L'exemple suivant charge les données à partir du tableau, et génère du RSS en sortie.

<?php 

$N 
= new newsFromArray;

$H renderer::create($N'RSS');
echo 
$H->display();

?>

Liens utiles

Conclusion

Nous constatons que l'utilisation devient uniforme et très modulable selon le contexte. A partir d'une même classe factorisée, nous pouvons charger nos données en provenance d'origines diverses, et générer un code différent, tout cela en fonction du contexte, sans avoir à retoucher à la classe de base.

Fabrice Lezoray < fabrice AT scriptsphp.org >. Merci à microtom pour la relecture.

Trackback

Il n'y a pas de trackback recensé pour cet article.

Faire un trackback sur cet article http://classes.scriptsphp.org/Trackbackserver.Le-design-pattern-Factory, récupérer les trackback sur cet article

Merci de ne pas suivre ce lien emails.

0.0712s | «»
PHP powered