PHP-Subject Observer-

Ajouter un commentaire

Le principe du motif de conception Sujet observateur est de permettre à une classe Sujet d’observer certaines événements et d’en notifier des observateurs qu’elle aura préalablement attachés afin qu’ils réagissent à l’événement

Concrètement, ce design patter participe donc à la réduction du couplage applicatif en permettant à chaque objet d’avoir une responsabilité unique.

Principe du design pattern Subject Observer

// A la détéction d'un événement le sujet itère sur les observateurs
// et appelle leur méthode update
class Subject
{
    public function notify()
    {
      foreach ($observers as $observer) {
          $observer->update($this);
      }
    }
}

Le SPL facilite l’implémentation en mettant à disposition deux interfaces spécifiques à ce design pattern  :

  • SplSubject
  • SplObserver

pour implémenter respectivement le design pattern Subject et le design pattern Observer

Le Spl met aussi à disposition la classe SplObjectStorage qui permet le stockage d’objet de manière triviale

Un cas d’exemple classique serait un système de  log par exemple. Imaginons qu’à chaque fois qu’une information doit être loguée, elle doit l’être sur plusieurs supports (fichier plat, base de données, ticket d’un gestionnaire de tickets, webservice, etc.), chaque support sera donc un observateur et le gestionnaire de logs sera le sujet

Exemple d’implémentation du sujet

<?php 
class Log implements SplSubject 
{ 
   const FORMAT = '%s : %s';
   private $observers = null; 
   private $msg; 
   public function __construct() 
   {
    $this->observers = new SplObjectStorage();
   }

    public function log($msg)
    {
       $this->msg = sprintf(self::FORMAT, date('Y-m-d h:i:s', time()), $msg);
       $this->notify(); 
    }
     
    public function attach(SplObserver $observer)
    {
        $this->observers->attach($observer);
    }

    public function detach(SplObserver $observer)
    {
        $this->observers->detach($observer);
    }

    public function notify()
    {
        foreach ($this->observers as $observer){
           $observer->update($this);
        }

    }
}

Cet exemple symbolise la classe Log se comportant comme Subject, elle implémente l’interface SplSubject qui l’oblige à définir trois méthodes (attach, detach et notify) qui permettent respectivement d’ajouter un ou plusieurs observateurs (Observer), de les supprimer et enfin de les notifier d’un événement intervenu.

La classe SplObjectStorage est utilisée afin de stocker les observateurs.

La méthode log permet ici de « journaliser »  un message simple. Cette méthode se contente d’enregistrer le message à « journaliser »  et d’en notifier les observateurs en invoquant leur méthode update

 

Exemple d’implémentation des observateurs

<?php 
class WriterFile implements SplObserver 
{ 
   private $file; 
   public function __construct($path) 
   { 
      $this->file = $path;
   }
   
   public function update(SplSubject $subject)
   {
      file_put_contents($this->file, $subject.PHP_EOL);
   }
}
class WriterDatabase implements SplObserver
{
    /*
     * corps de la classe
     */
}

Dans cet exemple, seule la classe WriterFile est détaillé pour comprendre le fonctionnement, la classe WriterDatabase ne sert qu’à comprendre qu’un sujet est capable de notifier tous les observateurs qui lui sont attachés. Chaque classe observatrice implémente l’interface SplObserver qui oblige la définition de la méthode update. Cette méthode est la seule connue par le sujet(Subject)

Exemple d’utilisation

 $logger = new Log;
$writeFile = new WriterFile(dirname(__FILE__). '/log/exemple.log');
$writeDatabase = new WriterDatabase(/*args*/);
$logger->attach($writerFile);
$logger->attach($writerDatabase);

$logger->log('un message');

Ceci illustre le découplage : le log se fait simplement en appelant lé méthode log de l’objet $logger qui se charge, lui, de notifier chaque observateur en charge de journaliser ce message sur différents supports (fichier, base de données)

 

Cet exemple est pris du livre : PHP 5.5 – Préparation à la certification Zend Certified PHP Engineer (ZCPE) de Cyrille Grandval,Julien Charpentier ( 8 avril 2015 )