Wzorzec projektowy Fasada - okładka

Wzorzec projektowy Fasada

Opublikowano Kategorie Czysty kodCzas czytania 5min

Wzorzec projektowy Fasada to kolejny ze wzorców projektowych opisanych w książce Design Patterns: Elements of Reusable Object-Oriented Software przez tzw. bandę czworga (Gang of Four) – Gamma Erich, Helm Richard, Johnson Ralph oraz Vlissides John. Jest to jeden ze wzorców należących do kategorii wzorców strukturalnych. Jeśli chcesz poznać inne wzorce projektowe lub dowiedzieć się czym są wzorce, to koniecznie sprawdź mój wpis o wzorcach projektowych.

Charakterystyka wzorca Fasada

Tak jak w wielu innych wzorcach, tak i w przypadku Fasady łatwo można odnaleźć analogie w świecie rzeczywistym. Fasadą, z którą z pewnością się spotkałeś/aś jest bankomat. Bankomat jest interfejsem pośredniczącym między bankiem, dzięki któremu można:

  • wypłacić środki z konta za pomocą karty płatniczej,
  • wypłacić środki z konta za pomocą kodu BLIK,
  • sprawdzić stan konta.

Dzięki bankomatowi — Fasadzie, cała komunikacja między użytkownikiem a bankiem jest ukryta. Użytkownik nie musi wiedzieć, jak działa BLIK, nie musi przepisywać danych z karty, ani nawet wiedzieć, do jakiego oddziału banku jest przypisany. Interakcja z użytkownikiem ograniczona jest do absolutnego minimum.

Takie same założenia zostały przyjęte dla wzorca projektowego Fasada. Ma ona za zadanie ukryć wszelkie szczegóły implementacyjne i detale, które nie są do niczego potrzebne użytkownikowi. Jednocześnie Fasada ma zadanie wystawić przyjazny interfejs dla użytkownika docelowego.

Praktyczny przykład

Mając już za sobą teoretyczny wstęp, czas przejść do praktyki. W tej części artykułu przedstawię Ci praktyczne zastosowanie wzorca Fasada. Postawionym zadaniem będzie zaprojektowanie aplikacji, która ma jedną publiczną metodę, która oczekuje podania treści w formacie kodu HTML oraz oczekiwanego formatu pliku wynikowego. Rezultatem zwróconym z omawianej metody ma być plik w podanym formacie. Diagram klas UML dla omawianego rozwiązana wygląda następująco.

Wzorzec Fasada - diagram UML

Przedstawione rozwiązanie pozwala na wygenerowanie dokumentu w formatach: DOCX, PDF i Markdown. Interfejs ogranicza interakcję z użytkownikiem do wymagań określonych wcześniej — jedna metoda z dwoma parametrami. Dzięki temu użytkownik nie musi wiedzieć absolutnie nic o tym, jak aplikowane są przykładowo czcionki czy zdjęcia w dokumentach w wymienionych formatach. Powyższy diagram klas UML zaimplementowany w TypeScript wygląda następująco.


interface IPrinter {
    getFormat(): string;
    print( content: string ): Promise<Buffer>;
}

class MarkdownPrinter implements IPrinter {
    private readonly _format: string = 'md';

    public getFormat(): string {
        return this._format;
    }

    public print( content: string ): Promise<Buffer> {
        // ... magic
    }
}

class DOCXPrinter implements IPrinter {
    private readonly _format: string = 'docx';

    public getFormat(): string {
        return this._format;
    }

    public print( content: string ): Promise<Buffer> {
        // ... magic
    }
}

class PDFPrinter implements IPrinter {
    private readonly _format: string = 'pdf';

    public getFormat(): string {
        return this._format;
    }

    public print( content: string ): Promise<Buffer> {
        // ... magic
    }
}

class DocumentFacade {
    private readonly _printers: IPrinter[];

    public constructor() {
        this._printers = [
            new DOCXPrinter(),
            new MarkdownPrinter(),
            new PDFPrinter()
        ];
    } 

    public printDocument( format: string, content: string ): Promise<Buffer> {
        const printer: IPrinter | undefined = this._printers.find( printer => printer.getFormat() === format );

        if ( !printer ) {
            throw new Error( 'Document format not supported.' );
        }

        return printer.print( content );
    }
}

Powyższy kod w formie interaktywnej znajdziesz pod tym linkiem. W dalszych etapach rozwoju tego programu nic nie stoi na przeszkodzie, by przykładowo podpisywać czy szyfrować generowany dokument poprzed dodatkową metodę w klasie DocumentFacade lub dodatkowy parametr w metodzie printDocument.

Analogie do innych wzorców projektowych

Różnica między Fasadą a Proxy jest to, że celem Proxy jest pośredniczenie między użytkownikiem a kodem docelowym. Przykładowo, chcąc wykonać zapytanie HTTP o obecną temperaturę powietrza w podanej lokalizacji, w przypadku Proxy, oczekiwałbym interfejsu pozwalającego zdefiniować URL, metodę, nagłówki itp. Samo Proxy dodawałoby tylko nagłówki uwierzytelniające. Natomiast w przypadku Fasady zaimplementowałbym metodę do pobierania temperatury, która wymaga jedynie podania miasta, dla którego wykonane ma być zapytanie. Użytkownik nawet nie wiedziałby o tym, że wewnątrz klasy wykonane jest zapytanie HTTP.

Różnica między Fabryką a Fasadą wynika głównie z celu powstania klasy — Fabryka służy do ukrycia szczegółów konstrukcji wytwarzanych obiektów, z kolei Fasada służy ukryciu szczegółów implementacyjnych zaimplementowanego mechanizmu i wystawieniu przyjaznego interfejsu.

Adapter różni się od Fasady tym, że założeniem Adaptera jest zapewnienie kompatybilności między dwoma niekompatybilnymi interfejsami.

Zdarza się też tak, że Fasada jest jednocześnie Singletonem.

Podsumowanie

Mam nadzieję, że idea oraz cel stosowania wzorca projektowego Fasada jest już dla Ciebie zrozumiała! Serdecznie zachęcam do pozostawienia komentarza, szczególnie jeśli masz jakieś uwagi lub wątpliwości. Będzie mi również bardzo miło, jeśli udostępnisz ten wpis, aby trafił do większej liczby czytelników.

Źródła i materiały dodatkowe:

Dominik Szczepaniak

Zawodowo Senior Software Engineer w CKSource. Prywatnie bloger, fan włoskiej kuchni, miłośnik jazdy na rowerze i treningu siłowego.

Inne wpisy, które mogą Cię zainteresować

Zapisz się na mailing i odbierz e-booka

Zapisując się na mój mailing, otrzymasz darmowy egzemplarz e-booka 106 Pytań Rekrutacyjnych Junior JavaScript Developer! Będziesz też otrzymywać wartościowe treści i powiadomienia o nowych wpisach na skrzynkę e-mail.

Subscribe
Powiadom o
guest

1 Komentarz
oceniany
najnowszy najstarszy
Inline Feedbacks
View all comments
Dominik
Dominik
9 miesięcy temu

Dość ciekawie przedstawiony temat, dzięki!