Exemple d'utilisation du Proxy
Vous trouverez dans cet article un exemple d'utilisation du patron de conception Proxy en PHP.
Définition
Un proxy est un intermédiaire entre la partie cliente et un objet. Le proxy implémente la même interface que la classe à laquelle il se substitue.
L'utilisation du proxy permet de contrôler l'accès aux méthodes de la classe substituée. Il permet aussi de simplifier l'utilisation d'un objet complexe ou d'éviter de manipuler un objet qui est trop consommateur de ressource.
Exemple
On veut manipuler un objet image. Cependant, on veut éviter de consommer trop de mémoire car nos images peuvent être très lourdes. Le patron de conception Proxy va nous être utile ici.
On commence par créer notre interface qui va être commune au proxy et à l'objet image :
/**
* Interface ImageInterface
*/
interface ImageInterface
{
public function display();
}
Elle demande d'implémenter une méthode permettant d'afficher l'image.
Ensuite on crée notre classe Image qui va implémenter cette interface :
/**
* Class Image
*/
class Image implements ImageInterface
{
/**
* @var string
*/
private $fileName;
/**
* Image constructor.
*
* @param string $fileName
*/
public function __construct(string $fileName)
{
$this->fileName = $fileName;
$this->load($fileName);
}
/**
* @inheritdoc
*/
public function display()
{
echo "Affichage de l'image : {$this->fileName}";
}
/**
* @param string $fileName
*/
private function load(string $fileName)
{
// Ici se trouve le code de chargement de l'image
echo "Chargement de l'image : $fileName";
}
}
Comme vous pouvez le voir, lorsque l'on instancie la classe Image, le constructeur va automatiquement charger l'image en mémoire. Dans certains cas, on veut pouvoir manipuler un objet image sans que l'image soit chargée directement. La deuxième problématique est que le temps de chargement peut être long. On veut éviter de faire attendre l'utilisateur, surtout si au final, l'image ne va pas être affichée.
L'utilisation d'un proxy va nous permettre de régler ces 2 problèmes :
/**
* Class ImageProxy
*/
class ImageProxy implements ImageInterface
{
/**
* @var string
*/
private $fileName;
/**
* @var Image
*/
private $image;
/**
* ImageProxy constructor.
*
* @param string $fileName
*/
public function __construct(string $fileName)
{
$this->fileName = $fileName;
}
/**
* @inheritdoc
*/
public function display()
{
if (!$this->image) {
$this->image = new Image($this->fileName);
}
$this->image->display();
}
}
Avec ce proxy, l'image va être chargée uniquement si on décide de l'afficher et pas avant. Pour cela, l'objet image est instancié au premier appel de la méthode display().
Il ne reste plus qu'à écrire le code client qui va manipuler le proxy à la place de l'objet lui-même :
$imageProx = new ImageProxy('/home/images/77.png');
$imageProx->display();
$imageProx->display();
On obtient l'affichage ci-dessous. L'image est bien chargée uniquement lors du premier affichage :
Chargement de l'image : /home/images/77.png
Affichage de l'image : /home/images/77.png
Affichage de l'image : /home/images/77.png