Fasada upraszcza oraz unifikuje dostęp do grupy klas lub jednej klasy o rozbudowanym API. Fasada tworzy nowy interfejs o wysokiej abstrakcji, który upraszcza korzystania z całego systemu.
W praktyce z fasadą możemy spotkać się w sytuacji, gdy tworzymy serwis rozdzielony na frontend oparty na technologiach webowych (Java Script, HTML, CSS, itd.) i backend gdzie komunikacja odbywa się przy pomocy zapytań RESTowych. Wtedy dobrze jest na wejściu backendu zastosować wzorzec Fasada, który dostarczy jedno zunifikowane API, a resztę poupychać po podserwisach odpowiedzialnych za każdy element z danej dziedziny. Fasada może pełnić również rolę adaptera kiedy dokonuje konwersji interfejsu, np. może to wystąpić w przypadku gdy w nowej wersji biblioteki której używamy zostało zastosowane nowe niekompatybilne API.
Zalety:
- Jeden punkt styku systemu z naszym rozbudowanym systemem. Możemy dokonywać zmian bez konieczności informowania systemu Klienta o tym że coś zmodyfikowaliśmy
- W przypadku monolitycznego systemu, którego chcemy przerobić na mikroserwisy, na wejściu monolita można postawić fasadę. Możemy wtedy spokojnie przełączać poszczególne elementy naszego systemu bez obawy, że coś u klienta się popsuje.
- Możemy w jednym miejscu dokonać transformacji danych, logowania co się dzieje
- Fasada może być również mechanizmem filtrującym, który zatrzyma nie zautoryzowany ruch
Wady:
- Jak przestanie działać serwis, który stanowi fasadę, to Klient odnosi wrażenie że pada cały system. Ale w praktyce można się przeciw temu zabezpieczyć stosując load balancery, proxy typu High Availability, itd.
Przykład:
System sterowania domem, który implementuje wiele różnych podsystemów, a chcemy mieć jedno uniwersalne API. Więc na wejściu zastosujemy fasadę.
interface Light{ void on(); void off(); } interface Door{ void open(); void close(); void lock(); void unlock(); } class HallLight implements Light{ @Override public void on(){ System.out.println("Hall light on."); } @Override public void off(){ System.out.println("Hall light off."); } } class LivingRoomLight implements Light{ @Override public void on(){ System.out.println("Living room light on."); } @Override public void off(){ System.out.println("Living room light off."); } } class MainDoor implements Door{ @Override public void open(){ System.out.println("Main door open."); } @Override public void close(){ System.out.println("Main door close."); } @Override public void lock(){ System.out.println("Main door lock."); } @Override public void unlock(){ System.out.println("Main door unlock."); } } class GarageDoor implements Door{ @Override public void open(){ System.out.println("Garage door open."); } @Override public void close(){ System.out.println("Garage door close."); } @Override public void lock(){ System.out.println("Garage door lock."); } @Override public void unlock(){ System.out.println("Garage door unlock."); } } class MainApi{ private Light livingRoomLight = new LivingRoomLight(); private Light hallLight = new HallLight(); private Door mainDoor = new MainDoor(); private Door garageDoor = new GarageDoor(); public void lockHome(){ System.out.println("------ LOCK HOME -----"); livingRoomLight.off(); hallLight.off(); mainDoor.lock(); garageDoor.lock(); } public void unlockHome(){ System.out.println("------ UNLOCK HOME -----"); hallLight.on(); mainDoor.unlock(); garageDoor.unlock(); } public void lightOff(){ System.out.println("------ LIGHT OFF -----"); livingRoomLight.off(); hallLight.off(); } public void lightOn(){ System.out.println("------ LIGHT ON -----"); livingRoomLight.on(); hallLight.on(); } } public class DesignPatternsFacade{ public static void main(String[] args){ MainApi mainApi = new MainApi(); mainApi.lockHome(); mainApi.unlockHome(); mainApi.lightOn(); mainApi.lightOff(); } } |
Możliwość komentowania jest wyłączona.