post_ico4

Wzorce projektowe, cz. 10 Facade

Fasada służy do ujednolicenia dostępu do złożonego systemu poprzez udostępnienie uproszczonego i uporządkowanego interfejsu programistycznego. Fasada zwykle implementowana jest w bardzo prosty sposób – w postaci jednej klasy powiązanej z klasami reprezentującymi system, do którego klient chce uzyskać dostęp.


Diagram klas wzorca Facade

Przykładowa implementacja

<?php 

class Element1{
    public function method() {
        echo "metoda klasy Element1";
    }
}

class Element2{
    public function method() {
        echo "metoda klasy Element2";
    }
}

class Element3{
    public function method() {
        echo "metoda klasy Element3";
    }
}

class Facade{
    private $objects = array();
    
    public function __construct() {
        $this->objects[0] = new Element1();
        $this->objects[1] = new Element2();
        $this->objects[2] = new Element3();
    }
    
    public function method1() {
        $this->objects[0]->method();
    }
    
    public function method2() {
        $this->objects[1]->method();
    }
    
    public function method3() {
        $this->objects[2]->method();
    }
    
    public function apiElement1() {
        return $this->objects[0];
    }
}

// testy
$api = new Facade();
$api->method1(); // wyswietli "metoda klasy Element1"
$api->method2(); // wyswietli "metoda klasy Element2"
$api->method3(); // wyswietli "metoda klasy Element3"
var_dump($api->apiElement1());

?>

Klasa Facade zawiera obiekty klas, które stanowią elementy systemu. Wywołując metodę (method1(), method2(), method3()) tej klasy, tak naprawdę wywołujemy metody poszczególnych obiektów składowych systemu. Metoda apiElement1() jest pewnym „rozszerzeniem” fasady, która zwraca cały obiekt klasy Elemnt1 – rozwiązanie takie zezwala w łatwy sposób udostępniać całą bibliotekę wymaganą w specyficznych sytuacjach.

Przykład z życia wzięty

Mamy za zadanie stworzyć sklep internetowy, który ma umożliwić łatwą integrację z innymi serwisami. Do realizacji tego zadania musimy stworzyć API udostępniane partnerom. Najłatwiej użyć do tego wzorca fasady.

<?php 

class User{
    public function login() {
        echo "Logowanie do systemu\n";
    }
    public function register() {
        echo "Rejestracja\n";
    }
}

class Cart{
    public function getItems() {
        echo "Zawartość koszyka\n";
    }
}

class Product{
    public function getAll() {
        echo "Lista produktów\n";
    }
    
    public function get($id) {
        echo "Produkt o ID ".$id."\n";
    }
}

class API{
    private $user;
    private $cart;
    private $product;
    
    public function __construct() {
        $this->user = new User();
        $this->cart = new Cart();
        $this->product = new Product();
    }
    
    public function login() {
        $this->user->login();
    }
    
    public function register() {
        $this->user->register();
    }
    
    public function getBuyProducts() {
        $this->cart->getItems();
    }
    
    public function getProducts() {
        $this->product->getAll();
    }
    
    public function getProduct($id) {
        $this->product->get($id);
    }
}

// testy
$client = new API();
$client->register();
$client->login();
$client->getProducts();
$client->getProduct(5);
$client->getBuyProducts();

?>

Prawda, że dużo łatwiej korzystać z API niż odwoływać się bezpośrednio do składowych systemu? ;) Nie wspominając o kwestiach bezpieczeństwa…

Zalety i wady

Zalety:

  • Zmniejszenie liczby zależności między klientem, a złożonym systemem — jeśli klient nie korzysta bezpośrednio z żadnych elementów ukrytego za fasadą systemu, całość jest łatwiejsza w konserwacji i utrzymaniu.
  • Wprowadzenie podziału aplikacji na warstwy, który ułatwia niezależny rozwój elementów klienta i złożonego systemu.
  • Możliwość zablokowania klientowi drogi do bezpośredniego korzystania ze złożonego systemu, jeśli jest to konieczne.

Wady:

  • Są jakieś? ;)

Zastosowanie

Przykładem użycia wzorca fasady może być zbudowanie API, które zezwoli zewnętrznym serwisom i aplikacjom łączyć się w prosty sposób z naszą aplikacją.

Innym praktycznym przykładem jest system bankowy. Logując się na internetowe konto mamy dostęp tylko do pojedynczych składowych całego systemu (autoryzacja, przelewy, saldo konta itp).

Powiązane tematy

Co sądzisz o wpisie?
BeżnadziejnySłabyŚredniDobryBardzo dobry (Brak ocen, bądź pierwszy!)
Loading...
  • ze4lot

    Wg. mnie konstruktor nie powinien ładować obiektów tylko powinny one być tworzone tylko kiedy są potrzebne ale świetnie zdaję sobie sprawę, że przykład powyżej jest tylko ‚przykładem’ a nie kodem idealnym ;)

    Pozdrawiam i więcej wad też nie widzę.

  • W sumie zależy od sytuacji, niektóre obiekty warto tworzyć w konstruktorze, a niektóre „w miarę potrzeb” ;)