Wzorzec fasada

Wzorzec fasada jest podobny trochę do adaptera oraz dekoratora. Ich cechą wspólna jest to, że są wzorcami strukturalnymi. Fasadę można na początku pomylić z adapterem. Podobnie jak adapter modyfikuje interfejs aby łatwiej nam było z niego korzystać. Jednak służy całkowicie do innych celów.

Przykład z życia wzięty

Weźmy sobie taki samochód z automatyczną skrzynią biegów. Nie chcę tu zagłębiać się w nowoczesne rozwiązania tylko wziąć na warsztat najprostszy model.

Samochód z automatyczną skrzynią biegów jest łatwiejszy w obsłudze niż ten z ręczną skrzynią. Pokusiłbym się o stwierdzenie, że ma prostszy interfejs. Dźwignie biegów przesuwamy na jazdę do przodu i naciskamy pedał gazu i jedzie. Nie martwimy się niczym więcej.

W samochodzie z ręczną skrzynią jest to bardziej skomplikowane. Naciśnij sprzęgło. Wrzuć pierwszy bieg. Puszczaj powoli sprzęgło i dodawaj gazu. Rozpędź silnik do pewnej liczby obrotów. Naciśnij sprzęgło. Wrzuć wyższy bieg. I tak dalej.

Początkującym kierowcom naprawdę sprawia to dużo problemów. Ale nie o jeżdżeniu samochodem a o fasadzie. Z całą odpowiedzialnością mogę powiedzieć, że mechanizm, który obsługuje automatyczną skrzynię biegów jest fasadą.

Koncepcja fasady

  • Upraszanie API aby były bardziej łatwiejsze w użyciu
  • Zazwyczaj wzorzec wykorzystywany przy „refaktoryzacji”
  • Zmniejszenie ilość zależności w kodzie

Fasada nie hermetyzuje interfejsów bazowych. Cały czas mamy do nich dostęp.

Co to jest fasada?

Fasa jest wzorcem, który ma uprosić nam korzystanie ze skomplikowanego API.  Załóżmy, że masz skomplikowany mechanizm powiadomień w swoim systemie. Integracja z mailem, z wewnętrznymi notyfikacjami, hubem notyfikacji mobilnych itd. za każdym razem wykonujesz sekwencje poleceń. Czemu by tego nie uprościć? Do tego właśnie celu służy fasada.  Stwórz klase następnie metodę, SendNotify() i uprość swoje API.
Fasada w takim przypadku łączy wiele podsystemów w jeden ujednolicony interfejs.

Przykład w praktyce

Projekt posiada kilka klas obsługujących powiadomienia.

Korzystanie z wielu interfejsów wprowadza pewien nie ład. Każde miejsce, w kodzie z którego chcemy wysłać powiadomienie zmusza nas do wstrzyknięcia aż 4 interfejsów. Uprośmy to trochę korzystając z fasady.

Zamiast korzystać z czterech różnych klas do wysyłania powiadomień, wykorzystuje teraz jedną.  Klasy bazowe są właściwościami fasady, więc mogę bez problemu nadal z nich korzystać, jeżeli będzie taka potrzeba.

2 thoughts on “Wzorzec fasada

  1. M Bowzyk

    Wygląda aż za podobnie do czasami nadużywanego delegata. Poza tym zakłada znajomość pojedynczych obiektów, ponieważ trzeba je podać w konstruktorze. Więc przy tworzeniu obiektu fasady, i tak najpierw musisz potworzyć wcześniejsze obiekty. Więc upraszcza się tylko nie wywoływanie 4 metod, bo zamiast nich tworzymy w tym samym miejscu 5-ty obiekt i z niego coś wywołujemy. Chyba, że zakładasz istnienie potężnego systemu, gdzie te obiekty już będą przekazywane, wtedy to ma sens. Ale jak ma rzeczywiście uprościć, to fasada sama powinna się tym martwić… ale wtedy wyglądałaby jak delegat. Druga sprawa, taki długi konstruktor, jak dałeś, aż prosi się o najprostszego buildera, bo dawanie takich rozbudowanych ostatecznie mija się z celem i powoduje, że api wciąż jest skomplikowane i brzydkie, choć można dobrać się z jednego miejsca, a nie trzeba z kilku na raz.
    Poza tym nie podoba mi się używanie publicznych zmiennych wewnątrz klas, ale to pewnie można zaliczyć jako zboczenie z Javy 🙂

    • Sebastian Czarnecki

      Poza tym zakłada znajomość pojedynczych obiektów, ponieważ trzeba je podać w konstruktorze. Więc przy tworzeniu obiektu fasady, i tak najpierw musisz potworzyć wcześniejsze obiekty.

      Za tworzenie i wstrzykiwanie w normalnej aplikacji odpowiadał by kontener IoC, więc nie musimy się martwić tworzeniem tych obiektów.

      Więc upraszcza się tylko nie wywoływanie 4 metod, bo zamiast nich tworzymy w tym samym miejscu 5-ty obiekt i z niego coś wywołujemy.

      Kod który zademonstrowałem jest dość naiwny. Oczywiście samo wysyłanie notyfikacji mailowej może tak naprawdę składać się z wielu metod. W moim przykładzie jest po jednej metodzie ale to ze względu na czytelność przykładu. W praktycznym zastosowaniu zazwyczaj będzie to bardziej skomplikowane.

      Druga sprawa, taki długi konstruktor, jak dałeś, aż prosi się o najprostszego buildera, bo dawanie takich rozbudowanych ostatecznie mija się z celem i powoduje, że api wciąż jest skomplikowane i brzydkie, choć można dobrać się z jednego miejsca, a nie trzeba z kilku na raz.

      Myślę, że tego konstruktora nie da się skrócić. Musimy jakoś wstrzyknąć obiekty podsystemu do fasady. Oczywiście zgadzam się z tobą, że to może urosnąć do 20 podsystemów i zaczyn się problem. Jednym rozwiązań go jest tworzenie subfasad. Czyli tworzymy kilka mniejszych fasad, którą później łączymy w jedną. Jest to trudne zadanie, żeby zrobić to dobrze ale nie koniecznie najlepsze. Wydaje mi się, że są to już zagadnienia, gdzie nie jest coś dobre albo złe. Odpowiedź będzie zależna na pewno od kontekstu i będzie należeć do zbioru rozmytego.

      Poza tym nie podoba mi się używanie publicznych zmiennych wewnątrz klas, ale to pewnie można zaliczyć jako zboczenie z Javy

      W klasach C# istnieją jakby dwa rodzaje „zmiennych”.

      – Field, to również istnieje w Javie, czyli taka zwykła zmienna, która powinna być raczej prywatna

      – Property, tego nie ma w Javie i bardzo mi tego tam brakuje

      Property to coś co jest elementem obiektu i raczej powinno być publiczne. Jest zgrabną konstrukcją, która zastępuje metody geterów i seterów w Javie. Ja w swoim przykładzie zastrzegłem, że ustawiać te właściwość można jedynie prywatnie oraz pozostawiłem domyślną wartość, czyli public dla get.

      Jeżeli chciałbyś więcej informacji na temat czym różni się property od fielda w C# odsyła do http://stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property-in-c

Comments are closed.