Les Design Patterns
(PHP)
Achref El Mouelhi
02 Novembre 2017, POEC PHP 2017 1 / 34
Plan
1 Introduction
2 Les design patterns : création
Singleton
Factory
3 Les design patterns : structure
Adapter
4 Les design patterns : comportement
Observer
5 Liens utiles
02 Novembre 2017, POEC PHP 2017 2 / 34
Introduction
C’est quoi en français ?
Plusieurs traductions possibles
Motifs de conception
Patrons de conception
Masques de conception
Modèle de conception
...
02 Novembre 2017, POEC PHP 2017 3 / 34
Introduction
C’est quoi exactement ?
Définition
Chaque patron décrit un problème qui se manifeste constamment
dans notre environnement, et donc décrit le cœur de la solution à ce
problème, d’une façon telle que l’on puisse réutiliser cette solution des
millions de fois, sans jamais le faire deux fois de la même manière.
L’architecte anglais Christopher Alexander
(A Pattern Language 1977)
02 Novembre 2017, POEC PHP 2017 4 / 34
Introduction
C’est quoi exactement ?
Définition
Chaque patron décrit un problème qui se manifeste constamment
dans notre environnement, et donc décrit le cœur de la solution à ce
problème, d’une façon telle que l’on puisse réutiliser cette solution des
millions de fois, sans jamais le faire deux fois de la même manière.
L’architecte anglais Christopher Alexander
(A Pattern Language 1977)
L’idée a été reprise et détaillée par la suite dans le livre Elements of
Reusable Object-Oriented Software en 1995 par le Gang of Four
(GoF, la bande des quatre en français) Erich Gamma, Richard Helm,
Ralph Johnson et John Vlissides).
02 Novembre 2017, POEC PHP 2017 4 / 34
Introduction
Catégories
Catégories de Design Patterns
Création (fabrication, construction...) : description de la façon dont
un (ou plusieurs) objet(s) peu(ven)t être créé(s), initialisé(s), et
configuré(s)
Structure : description de la manière dont doivent être liés des
objets afin de rendre ces connections indépendantes des
évolutions futures de l’application
Comportement : description de l’interconnexion entre objets
02 Novembre 2017, POEC PHP 2017 5 / 34
Introduction
C’est quoi ?
23 Design patterns proposés
Création : Singleton, Factory, Builder, Prototype...
Structure : Adapter, Bridge, Composite, Decorator...
Comportement : Iterator, Observer, Visitor, Strategy...
02 Novembre 2017, POEC PHP 2017 6 / 34
Introduction
C’est quoi ?
Remarques
les design patterns ne sont pas relatifs à un langage de
programmation
ils sont très adaptés aux langages de programmation
orientés-objets
ils offrent des solutions à des problématiques récurrents
rencontrés par les développeurs
certains motifs ont été pris en charge par des langages de
programmation (Java et Observable...)
02 Novembre 2017, POEC PHP 2017 7 / 34
Les design patterns : création Singleton
Sémantique
Problématique et solution
Une instance qu’on ne peut instancier qu’une seule fois
l’unicité de l’instance est complètement contrôlée par la classe
elle-même
Mettre en privé le constructeur ? ⇒ insuffisant car la classe n’est
plus instanciable
Un traitement additionnel par une méthode autre que le
constructeur
02 Novembre 2017, POEC PHP 2017 8 / 34
Les design patterns : création Singleton
Singleton : principe
<?php
class ClassSingleton
{
private static $_instance; // l’instance singleton de la
classe
private function __construct() { } // constructeur private
private function __clone() { } // clonage private
public static function getInstance()
{
if (!isset(self::$_instance)) // pas encore instanciee
{
self::$_instance = new self; // instanciation
}
return self::$_instance;
}
}
?>
02 Novembre 2017, POEC PHP 2017 9 / 34
Les design patterns : création Singleton
Singleton : exemple
class ClassSingleton
{
private $_value;
private static $_instance;
private function __construct() { }
private function __clone() { }
public static function getInstance()
{
if (!isset(self::$_instance)) // pas encore
instanciee
{
self::$_instance = new self; //
instanciation
}
return self::$_instance;
}
02 Novembre 2017, POEC PHP 2017 10 / 34
Les design patterns : création Singleton
Singleton : exemple
public function Value(){
return $this->_value;
}
public function setValue($value){
$this->_value = $value;
}
}
$a = ClassSingleton::getInstance();
$a->setValue(5);
$b = ClassSingleton::getInstance();
echo $b->Value(); // affiche 5
02 Novembre 2017, POEC PHP 2017 11 / 34
Les design patterns : création Singleton
Sémantique
Remarque
Évidemment, ce motif peut facilement être étendu pour permettre la
création d’un nombre bien déterminé d’instances
02 Novembre 2017, POEC PHP 2017 12 / 34
Les design patterns : création Factory
Sémantique
Problématique et solution
On veut automatiser par exemple l’instanciation d’une classe
(création d’objets)
ceci peut nous aider par exemple à remplir une table de notre
base de données avec des données aléatoires pour qu’on puisse
tester notre application
Déléguer la création d’objets à une classe Factory qui fabriquera
des objets en fonction de nos paramètres
02 Novembre 2017, POEC PHP 2017 13 / 34
Les design patterns : création Factory
Factory : exemple
//classe abstraite Personne
abstract class Personne{
private $_nom;
private $_prenom;
public function Nom(){
return $this->_nom;
}
public function Prenom(){
return $this->_prenom;
}
public function setNom($nom){
$this->_nom = $nom;
}
public function setPrenom($prenom){
$this->_prenom = $prenom;
}
abstract public function description();
}
02 Novembre 2017, POEC PHP 2017 14 / 34
Les design patterns : création Factory
Factory : exemple
// classe Etudiant heritant de Personne
class Etudiant extends Personne{
private $_niveau;
public function __construct($nom,$prenom,$niveau){
parent::setNom($nom);
parent::setPrenom($prenom);
$this->setNiveau($niveau);
}
public function Niveau(){
return $this->_niveau;
}
public function setNiveau($niveau){
$this->_niveau = $niveau;
}
public function description(){
echo ’<br/> Je suis Etudiant et je suis en ’ .
$this->Niveau();
}
}Novembre 2017, POEC PHP 2017
02 15 / 34
Les design patterns : création Factory
Factory : exemple
// classe Enseignant heritant de Personne
class Enseignant extends Personne{
private $_salaire;
...
public function description(){
echo "Je suis Enseignant et je touche " . $this->
Salaire();
}
}
// classe Administratif heritant de Personne
class Administratif extends Personne{
private $_affectation;
...
public function description(){
echo "Je suis Administratif et je suis affecte a
" . $this->Affectation();
}
}
02 Novembre 2017, POEC PHP 2017 16 / 34
Les design patterns : création Factory
Factory : exemple
include ’[Link]’;
include ’[Link]’;
include ’[Link]’;
include ’[Link]’;
// classe de fabrication
class FactoryPersonne{
public static function build($nom,$prenom,$valeur,
$type){
if (class_exists($type)){
$instance = new $type($nom,$prenom,$valeur);
return $instance;
}
else{
throw new Exception(" classe $type
inexistante ");
}
}
}
02 Novembre 2017, POEC PHP 2017 17 / 34
Les design patterns : création Factory
Factory : exemple
try {
$etudiant = FactoryPersonne::build(’bob’,’joe’,’1er
annee licence’,’Etudiant’);
$etudiant->description();
// affiche Je suis Etudiant et je suis en 1er annee
licence
$agriculteur = FactoryPersonne::build(’jack’,’dalton’
,’raisin’, ’Agriculteur’);
// affiche classe Agriculteur inexistante
}
catch (Exception $e){
echo $e->getMessage();
}
02 Novembre 2017, POEC PHP 2017 18 / 34
Les design patterns : création Factory
Factory : exemple
// classe qui controle la generation des instances
class ControllerPersonne{
// methode pour generer les valeurs de mes attributs
public static function buildRandomString($length=5){
$myDB = ’
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW
’;
$ch=’’;
for ($i = 0; $i< $length ; $i++){
$ch .= $myDB[rand(0, strlen($myDB)-1)];
}
return $ch;
}
}
// selon nos besoins, on peut definir d’autres methodes
comme buildRandomInteger, buildRandomKey...
02 Novembre 2017, POEC PHP 2017 19 / 34
Les design patterns : création Factory
Factory : exemple
// exploitation des classes FactoryPersonne et
ControllerPersonne
for($j=0; $j<5;$j++){
$tab[$j] = FactoryPersonne::build(ControllerPersonne
::buildRandomString(),ControllerPersonne::
buildRandomString(),ControllerPersonne::
buildRandomString(),’Etudiant’);
$tab[$j]->description();
}
/* le resultat semblerait
Je suis Etudiant et je suis en uPPRC
Je suis Etudiant et je suis en nQVOR
Je suis Etudiant et je suis en YwqmE
Je suis Etudiant et je suis en lSdVP
Je suis Etudiant et je suis en KteiF
*/
02 Novembre 2017, POEC PHP 2017 20 / 34
Les design patterns : création Factory
Sémantique
Remarque
Évidemment, ces classes peuvent être utilisées avec des classes
manager pour alimenter une base de données
02 Novembre 2017, POEC PHP 2017 21 / 34
Les design patterns : structure Adapter
Sémantique
Problématique et solution
On veut utiliser une classe existante mais sa structure ne coı̈ncide
pas avec celle attendue
nom des méthodes
nombre d’attributs ou leurs types
utiliser un adaptateur de cette classe sans avoir besoin de la
modifier
02 Novembre 2017, POEC PHP 2017 22 / 34
Les design patterns : structure Adapter
Adapter : principe
// une interface IPersonne
interface IPersonne{
public function descriptionPersonne();
}
// une classe Enseignant qui implemente IPersonne
class Enseignant implements IPersonne{
private $_nom;
public function __construct($nom){
$this->_nom = $nom;
}
public function Nom(){
return $this->_nom;
}
public function setNom($nom){
$this->_nom = $nom;
}
public function descriptionPersonne(){
echo "</br> Je m’appelle " . $this->Nom();
}
}
02 Novembre 2017, POEC PHP 2017 23 / 34
Les design patterns : structure Adapter
Adapter : principe
//classe Etudiant ne contenant pas la methode
descriptionPersonne
class Etudiant{
private $_nom;
private $_niveau;
public function __construct($nom,$niveau){
$this->setNom($nom);
$this->setNiveau($niveau);
}
public function Nom(){
return $this->_nom;
}
public function setNom($nom){
$this->_nom = $nom;
}
public function Niveau(){
return $this->_niveau;
}
02 Novembre 2017, POEC PHP 2017 24 / 34
Les design patterns : structure Adapter
Adapter : principe
public function setNiveau($niveau){
$this->_niveau = $niveau;
}
// cette classe a deux methodes une qui affiche le nom et
une deuxieme qui affiche le niveau
public function descriptionNom() {
echo "</br> Je m’appelle " . $this->Nom();
}
public function descriptionNiveau(){
echo " Je suis en " . $this->Niveau();
}
}
02 Novembre 2017, POEC PHP 2017 25 / 34
Les design patterns : structure Adapter
Adapter : principe
// creation d’une classe adaptateur qui permettra d’avoir la
methode descriptionPersonne sans rien modifier dans la
classe Etudiant
class EtudiantAdapter implements IPersonne{
private $_etudiant;
public function __construct(Etudiant $etudiant){
$this->_etudiant= $etudiant;
}
public function Etudiant(){
return $this->_etudiant;
}
public function descriptionPersonne(){
$this->Etudiant()->descriptionNom();
$this->Etudiant()->descriptionNiveau();
}
}
02 Novembre 2017, POEC PHP 2017 26 / 34
Les design patterns : structure Adapter
Adapter : principe
// pour tester
$personne[0]= new Enseignant(’bob’);
$personne[1]= new Enseignant(’joe’);
$personne[2]= new EtudiantAdapter(new Etudiant(’mickael’,’1ere
annee licence’));
$personne[3]= new EtudiantAdapter(new Etudiant(’jack’,’2eme
annee master’));
foreach ($personne as $value)
{
$value->descriptionPersonne();
}
/*
le resultat est :
Je m’appelle bob
Je m’appelle joe
Je m’appelle mickael Je suis en 1ere annee licence
Je m’appelle jack Je suis en 2eme annee master
*/
02 Novembre 2017, POEC PHP 2017 27 / 34
Les design patterns : comportement Observer
Sémantique
Problématique et solution
on veut assurer la cohérence entre des classes coopérant entre
elles tout en maintenant leur indépendance
l’objet, dont on veut suivre le changement de ses états, doit
implémenter une interface qui offre trois méthodes permettant de
s’abonner (s’attacher, s’inscrire...), se désabonner et notifier les
abonnés
les objets qui veulent être informés doivent implémenter une
interface qui offre une méthode update()
02 Novembre 2017, POEC PHP 2017 28 / 34
Les design patterns : comportement Observer
Observer : exemple
// l’interface observer qui definit la methode update qui sera
utiliser pour informer les abonnes
interface Observer{
public function update(Subject $subject);
}
// l’interface sujet qui permet de s’inscrire a un sujet, se
desinscrire et notifier les abonnes
interface Subject{
public function subscribe(Observer $o);
public function unsubscribe(Observer $o);
public function notify();
}
02 Novembre 2017, POEC PHP 2017 29 / 34
Les design patterns : comportement Observer
Observer : exemple
class Match implements Subject{
private $_score;
private $_observers = array();
public function __construct($score){
$this->setScore($score);
}
public function Score(){
return $this->_score;
}
public function setScore($score){
$this->_score = $score;
$this->notify();
}
02 Novembre 2017, POEC PHP 2017 30 / 34
Les design patterns : comportement Observer
Observer : exemple
public function subscribe(Observer $o){
$this->_observers[] = $o;
echo "<br/> une inscription : " . $o->Name();
}
public function unsubscribe(Observer $o){
$hint = array_search($o,$this->_observers,true);
if ($hint){
echo "<br/> une desinscription " . $this->
_observers[$hint]->Name();
unset($this->_observers[$hint]);
}
}
public function notify(){
for ($i=0;$i<count($this->_observers);$i++){
if (isset($this->_observers[$i])){
$this->_observers[$i]->update($this);
}
}
}
}
02 Novembre 2017, POEC PHP 2017 31 / 34
Les design patterns : comportement Observer
Observer : exemple
class Footeux implements Observer{
private $_name;
public function __construct($name){
$this->setName($name);
}
public function Name(){
return $this->_name;
}
public function setName($name){
$this->_name = $name;
}
public function update(Subject $sujet){
echo ’<br/> changement de score OM - PSG ’ . $sujet->
Score();
}
}
02 Novembre 2017, POEC PHP 2017 32 / 34
Les design patterns : comportement Observer
Observer : exemple
$m13 = new Footeux(’Marseillais’);
$p75 = new Footeux(’Parisien’);
$l69 = new Footeux(’Lyonnais’);
$om_psg = new Match(’0-0’);
$om_psg->subscribe($m13);
$om_psg->setScore(’1-0’);
$om_psg->subscribe($p75);
$om_psg->subscribe($l69);
$om_psg->setScore(’2-0’);
$om_psg->unsubscribe($p75);
$om_psg->setScore(’3-0’);
/* le resultat est : une inscription : Marseillais
changement de score OM - PSG 1-0
une inscription : Parisien
une inscription : Lyonnais
changement de score OM - PSG 2-0
changement de score OM - PSG 2-0
changement de score OM - PSG 2-0
une desinscription Parisien
changement de score OM - PSG 3-0 */
02 Novembre 2017, POEC PHP 2017 33 / 34
Liens utiles
Liens utiles
Autres détails et exemples
[Link]
[Link] de conception
02 Novembre 2017, POEC PHP 2017 34 / 34