Tym razem zwięźle i lapidarnie na temat virtual proxy. Na początku warto wspomnieć, iż należy on do grupy wzorców strukturalnych i jest przedstawicielem licznej rodziny proxy. W języku polskim określenie to najczęściej tłumaczy się jako pośrednik lub pełnomocnik. Familia proxy skupia się na tworzeniu obiektu, którego zadaniem jest pośrednictwo względem innych obiektów. Wśród najczęściej spotykanych rodzajów, oprócz omawianego rzecz jasna, można śmiało wymienić:
- pełnomocnik ochraniający [protection proxy] – jego zadaniem jest określanie, czy obiekty chcące uzyskać dostęp do obiektu chronionego posiadają wymagane uprawnienia
- pełnomocnik zdalny [remote proxy] – jest pośrednikiem w dostępie do obiektów zdalnych
- pełnomocnik sprytnego wskaźnika (odwołania) [smart proxy] – gdy oprócz dostępu do obiektu konieczne staje się podjęcie dodatkowych akcji – czynności
Powróćmy jednak do głównego bohatera tego wpisu.
Virtual proxy
Zadaniem tego wzorca jest reprezentowanie obiektu, którego utworzenie jest kosztowne z punktu widzenia całego systemu. Virtual proxy usiłuje maksymalnie opóźnić ten proces, w międzyczasie starając się w pełni zastąpić właściwy obiekt. Kiedy jest on już dostępny, wszystkie żądania deleguje bezpośrednio do niego. Prześledźmy to na bardzo prostym przykładzie.
Zakładamy taki oto scenariusz. Na potrzeby naszej aplikacji wykonujemy skomplikowane obliczenia matematyczne. Mamy do tego dedykowaną klasę, jednak utworzenie jej instancji jest bardzo czasochłonne. Jesteśmy też w stanie część obliczeń (głównie tych prostszych) wykonać bez jej udziału. W takim wypadku użycie virtual proxy wydaje się doskonałym rozwiązaniem. Popatrzmy na poniższy fragment kodu, zwracając uwagę na zamieszczone komentarze.
// wspolny interfejs
// implementowany dla posrednika
// i klasy wlasciwej
interface Calculations
{
public function Sum ($a,$b);
public function Difference ($a,$b);
public function Even ($a);
}
Gdy posiadamy już interfejs, spójrzmy jak implementuje go klasa właściwa.
// zakladamy ze utworzenie instacji
// tej klasy jest czasochlonne
// i koniecznie tylko dla metody even
class Maths implements Calculations
{
public function Sum ($a,$b)
{
return $a + $b;
}
public function Difference ($a,$b)
{
return $a - $b;
}
public function Even ($a)
{
return !($a & 1);
}
}
I jak wygląda kod pośrednika wirtualnego.
// wirtualny posrednik tworzy instancje klasy
// wlasciwej tylko po wywolaniu metody Even. Zakladamy ze
// pozostale funkcje jest w stanie obsluzyc sam.
// Oczywiscie jesli obiekt wlasciwy juz istnieje
// deleguje zadania bezposrednio do niego
class MathsVirtualProxy implements Calculations
{
private $maths = null;
public function Sum ($a,$b)
{
if ($this->maths instanceof Maths)
return $this->maths->Sum($a,$b);
else
return $a + $b;
}
public function Difference ($a,$b)
{
if ($this->maths instanceof Maths)
return $this->maths->Difference($a,$b);
else
return $a - $b;
}
public function Even ($a)
{
if ($this->maths === null) {
$this->maths = new Maths();
}
return $this->maths->Even($a);
}
}
Zatem dopóki nie wywołamy metody Even(), dopóty nie zostanie utworzony obiekt klasy Maths, a VirtualProxyMaths będzie się go starał zastępować. Gdy instancja zostanie stworzona, to wszelkie odwołania będą kierowane już bezpośrednio do niej.
// przyklad aby spradzic jak to wyglada w praktyce $object = new MathsVirtualProxy(); var_dump($object->Sum(1,2)); var_dump($object); var_dump($object->Even(1)); var_dump($object);
Proszę pamiętać, iż przykład ten jest mocno „naciągany”. Miał on bowiem na celu proste wyjaśnienie omawianego wzorca, co mam nadzieję się udało.
4 Odpowiedzi : “virtual proxy”


mam pytanie na boku: czy potrzebny jest tutaj interfejs Calculations? Nie znam sie na programowaniu obiektowym za bardzo i zastanawiam sie czy to tez by zadzialalo, gdyby nie zdefiniowano interfejsu i dla obu klas nie dano implemets Calculations
Stosowanie interfejsów daje bardzo duże możliwości. Oczywiście w języku takim jak PHP, gdzie typowanie zmiennych jest dynamiczne, nie jest konieczny interfejs Calculations – odpowiadając na Twoje pytanie. W językach które nie posiadają takiego typowania możemy deklarować zmienne, które będą posiadać – implementować dany interfejs (deklarowanie zmiennych interfejsu). A to duży plus.
W przypadku PHP plusy takiego rozwiązania to np:
- tworzenie kodu łatwego na rozbudowę (programiście łatwiej zrozumieć jak działa system), a zamkniętego na modyfikację (ingerencja w kod poszczególnych klas).
- łatwe wykrywanie błędów (jeśli klasa nie implementuje wszystkich metod interfejsu od razu się o tym dowiesz)
Generalnie to temat na spotkanie przy piwku i długą dyskusję
Mam nadzieję, że tak w skrócie udało mi się odpowiedzieć na Twoje pytanie w sposób Ciebie satysfakcjonujący.
W sumie to o tym chyba posta napiszę, bo to dobry temat jest i bardzo rozległy, nie na jeden komentarz
czekam na posta