Dans ce tutoriel je vous propose de découvrir le design pattern adapter. Comme son nom l'indique le principe de ce type de classe est de permettre d'adapter un élément au contexte de notre application.

Cas pratique

Pour comprendre ce design pattern il est important de comprendre la problématique qu'il résoud. Par exemple, nous utilisons un système de cache dans notre application et nous avons définit une interface comme suit.

interface CacheInterface
{
    public function get($key);

    public function has($key);

    public function set($key, $value, $expiration = 3600);
}

Nous utilisons ensuite cette interface à différents endroits dans notre application.

class Hello
{

    public function sayHello(CacheInterface $cache)
    {
        if($cache->has('hello')) {
            return $cache->get('hello');
        } else {
            sleep(4); // On simule un script lent 
            $content = 'bonjour';
            $cache->set('hello', $content);
            return $content;
        }
    }

}

Avec le temps, on a envie d'améliorer notre système en utilisant une librairie tiers. Le problème est alors que cette librairie n'implémente pas notre interface.

$cache = new \Doctrine\Common\Cache\FilesystemCache(__DIR__ . '/cache');
//  On ne peut pas utiliser cette objet car il n'implémente pas notre CacheInterface :(

L'adapter

Pour résoudre cette incompatibilité on va créer un adapter qui implémentera notre interface et qui se chargera de faire le lien avec notre objet.

class DoctrineCacheAdapter implements CacheInterface {

    private $cache; // Notre objet venant d'une librairie tiers

    // On injecte notre objet dans le constructeur
    public function __construct(Doctrine\Common\Cache\Cache $cache)
    {
        $this->cache = $cache; 
    }

    // On map toutes les méthodes de l'interface aux méthodes de l'objet
    public function get($key)
    {
        return $this->cache->fetch($key);
    }

    public function has($key)
    {
        return $this->cache->contains($key);
    }

    public function set($key, $value, $expiration = 3600)
    {
        return $this->cache->save($key, $value, $expiration); 
    }
}

Cet adapter nous permet ensuite d'utiliser l'objet dans notre application :

$cache = new \Doctrine\Common\Cache\FilesystemCache(__DIR__ . '/cache');
// On "adapte" notre objet
$adapter = new DoctrineCacheAdapter($cache);
$hello = new Hello();
echo $hello->sayHello($adapter);