Kolejnym wzorcem projektowym, który omówię jest wzorzec Pośrednik (Proxy). Jest to wzorzec z grupy wzorców behawioralnych. Proxy jest wzorcem, który zastępuje obiekt o tym samym interfejsie i przed otrzymaniem dostępu do obiektu wykonuje się jakaś logika. Do czego może być użyty?
- Najpopularniejszym użyciem proxy jest ograniczenie dostępu do kosztownych obiektów do momentu kiedy one są potrzebne. Jest to dość dobrze opisane w Internecie więc pominę to użycie.
- Innym przykładem użycia proxy jest zabezpieczenie obiektu przed nieautoryzowanym dostępem.
- Kolejna sytuacja kiedy możemy użyć pośrednika to inna reprezentacja obiektu w zależności od określonych warunków, wyobraź sobie, że masz obiekt ProxyRepository i w zależności od pewnych warunków chcesz, aby dane były pobierane albo z MySQL, albo MongoDB. Proxy to umożliwia. ’
Podsumowując Proxy przekierowuje żądania do oryginalnego obiektu wtedy, kiedy powinny być przekierowane, a warunki zależą od typu Proxy.
Proxy w praktyce

Wzorzec proxy
Dobra dość teorii, zobacz na kod. Jako przykład wybrałem drugi rodzaj pośrednika, który chroni obiekt przed nieautoryzowanym dostępem. Wyobraź sobie, że posiadasz obiekt samochodu i ten samochód by jeździć(to nie jest tesla) potrzebuje kierowcy. Jednakże, aby kierowca mógł jeździć musi być trzeźwy. W programie posiadamy, metodę, która będzie jeździła samochodami i nie interesuje jej sprawdzanie czy kierowca jest trzeźwy, załatwi to Pośrednik.
Do stworzenia wzorca będę potrzebował kilku plików:
CarInterface – interfejs do samochodu posiadający metodę drive(Driver $driver), która po dostaniu obiektu Driver powinna pojechać samochodem
<?php namespace Rpodwika\Designpatterns\Behavioral\Proxy; /** * Interface CarInterface * @package Rpodwika\Designpatterns\Behavioral\Proxy */ interface CarInterface { /** * Method drives a car * * @param Driver $driver * * @return string */ public function drive(Driver $driver); }
Car – klasa implementująca interfejs samochodu, reprezentująca zachowanie pojazdu.
<?php namespace Rpodwika\Designpatterns\Behavioral\Proxy; /** * Class Car * @package Rpodwika\Designpatterns\Behavioral\Proxy */ class Car implements CarInterface { /** * @inheritdoc */ public function drive(Driver $driver) { return "I am driving a car"; } }
Driver – klasa reprezentująca kierowcę, lepiej byłoby stworzyć interfejs, ale by nie tworzyć wielu plików i by nie komplikować wzorca tym razem odbędzie się bez niego. Klasa zawiera pola reprezentujące kierowcę i właściwość $isDrunk, która mówi o tym, czy kierowca jest trzeźwy.
<?php namespace Rpodwika\Designpatterns\Behavioral\Proxy; /** * Class Driver * @package Rpodwika\Designpatterns\Behavioral\Proxy */ class Driver { /** * @var string */ private $name; /** * @var boolean */ private $isDrunk; /** * @param $name * @param $isDrunk */ public function __construct($name, $isDrunk) { $this->name = $name; $this->isDrunk = $isDrunk; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $name * * @return $this */ public function setName($name) { $this->name = $name; return $this; } /** * @return boolean */ public function isDrunk() { return $this->isDrunk; } /** * @param boolean $isDrunk * * @return $this */ public function setIsDrunk($isDrunk) { $this->isDrunk = $isDrunk; return $this; } }
Ostatnim niezbędnym plikiem jest ProxyCar który będzie reprezentował samochód, do którego, aby kierować, potrzebne jest bycie trzeźwym.
<?php namespace Rpodwika\Designpatterns\Behavioral\Proxy; /** * Class ProxyCar * @package Rpodwika\Designpatterns\Behavioral\Proxy */ class ProxyCar implements CarInterface { /** * @var CarInterface */ private $car; public function __construct() { $this->car = new Car(); } /** * @inheritdoc */ public function drive(Driver $driver) { if ($driver->isDrunk()) { return 'Driver cannot drive'; } return $this->car->drive($driver); } }
Klasa ta implementuje interfejs samochodu, ale w metodzie drive(Driver $driver) sprawdza przed oddaniem dostępu do oryginalnego obiektu samochodu, czy kierowca jest trzeźwy.
Teraz załóżmy, że mamy funkcje, która przyjmuje jako argument interfejs CarInterface.
$drunkDriver = new Driver('Driver a', true); $soberDriver = new Driver('Driver b', false); $car = new Car(); $smartCar = new ProxyCar(); function driveCar(CarInterface $car, Driver $driver) { $car->drive($driver); } driveCar($car, $drunkDriver); // funkcja pozwoli jechać pijanemu kierowcy driveCar($smartCar, $drunkDriver); // funkcja nie pozwoli na jazde pijanemu kierowcy driveCar($car, $soberDriver); // funkcja pozwoli jechać driveCar($smartCar, $soberDriver); // funkcja pozwoli jechać
Zauważ, że funkcja driveCar nie wie czy dostała ProxyCar czy Car i jej to nie interesuje, najważniejsze, że dostała klasę, która implementuje interfejs CarInterface, całe sprawdzenie jest w obiekcie pośrednika, który zachowuje się tak jak Car, ale w określonym przypadku nie pozwoli na dostęp do obiektu. I to właśnie jest cała esencja wzorca projektowego pośrednik.
Jeśli masz jakieś pytania, znalazłeś błąd lub masz sugestię co do artykułu pisz śmiało.
Cały kod dostępny jest w moim repozytorium na github gdzie znajdziesz implementacje innych wzorców projektowych.
Zostaw komentarz