Witamy w kolejnym artykule odnośnie pytań z rozmów kwalifikacyjnych! Dzisiaj poruszymy temat nieco bardziej szeroki w porównaniu do poprzednich tekstów, ponieważ dzisiaj się zajmiemy pytaniami dotyczącymi wzorców projektowych wykorzystywanych w programowaniu. Możecie również ten tekst potraktować jako swoistą ściągawkę z wzorców projektowych. Postaramy się Wam przybliżyć zasadę działania, cel oraz sposób pisania najpopularniejszych wzorców wykorzystywanych przy produkcji kodu. Gotowi? Zaczynamy!

Czym są wzorce projektowe? Dla czego są stosowane?

Wzorce projektowe reprezentują najlepsze praktyki stosowane przy produkcji kodu w językach, wykorzystujących zasady programowania obiektowego. Bardzo możliwe, że wiele z nich udało Ci się już stosować nawet ich nie znając! Umożliwiają one tworzenie czytelnego oprogramowania, które w jasny i czytelny sposób komunikuje się ze sobą. Największym plusem wzorców projektowych jest zdolność do szybkiego porozumiewania się programistów. Przykładowo, kiedy ktoś wspomina nam o widoku (w modelu MVC) to od razu wiemy, o czym mówimy. Dodatkowo same nazwy używanych klas we wzorcach mówią nam dużo o architekturze – np. używając klasy CookieFactory (Factory pattern) wiemy, że jej celem jest tworzenie obiektów typu Cookie!

>> Sprawdź nasze aktualne oferty w obszarze: Java Developer

Co wiesz o modelu MVC?

Model MVC (Model – View – Controller) odpowiada rozdziałowi aplikacji na trzy główne moduły: widok, model oraz kontroler. Każdy z modułów odpowiada za co innego. Widok odpowiada za interakcję z użytkownikiem oraz wyświetlanie danych pobranych z modelu. Widokiem jest ta część, którą widzisz na ekranie po wejściu na stronę internetową dużego banku: wszystkie okienka, bannery, menu oraz przyciski. Model odpowiada naszym danym, na których będziemy stosować nasze przekształcenia. Model może przechowywać dane w swojej pamięci, bądź komunikować się z podległą bazą danych (przykładowo mapowanie tabel z baz danych). Kontroler odpowiada za logikę aplikacji (logikę biznesową). Jest on swoistym „mózgiem” Twojej aplikacji, odpowiada on za przetwarzanie żądań wysyłanych przez widok oraz przetwarzanie danych otrzymanych od modelu.

Rys. 1 Architektura MVC (uproszczenie).

Czym jest Singleton? W jaki sposób się go implementuje?

Singleton jest to klasa, której możemy stworzyć tylko jeden obiekt w całej aplikacji. Singleton to również nazwa wykorzystującego tę klasę wzorca (Singleton Pattern). Aby wprowadzić do naszej aplikacji taki obiekt musimy stworzyć klasę, która posiada prywatny konstruktor, do którego odwołuje się metoda zwracająca jego instancję. Wykorzystuje się je w sytuacjach, kiedy chcemy być pewni, że istnieje tylko jeden obiekt tego typu klasy. Poniżej trochę kodu, aby ułatwić zrozumienie działania tego mechanizmu:

Rys. 2 Dwa sposoby inicjalizacji klas Singletonowych.

Czym jest Observer Pattern (wzorzec obserwatora)?

Ten wzorzec jest bardzo popularny w przypadku programów z rozbudowanym interfejsem graficznym. W tym wzorcu występuje obiekt, który jest naszym podmiotem (subject). Zakładamy, że akcje mogą wydarzyć się w obiekcie w dowolnym czasie (przykładowo, w naszym interfejsie graficznym może zostać naciśnięty jakiś guzik), lecz my nie jesteśmy w stanie stwierdzić, jaki dokładnie będzie to czas. Aby było to możliwe w międzyczasie musi działać menager zdarzeń, czyli nasz obserwator (Observer lub Listener). Manager będzie nasłuchiwał, czy przycisk został wciśnięty – w momencie naciśnięcia przycisku musi zostać wykonana jakaś czynność. Taki rodzaj programowania jest również nazywany Event Driven Programming (programowanie sterowane zdarzeniami). Przykład – w pracy wykonujesz swoje codzienne czynności, lecz w pewnym momencie dostajesz e-maila z poleceniem od swojego przełożonego, które następnie wykonujesz. W tym wypadku Ty byłeś Obserwatorem, Twój Szef był podmiotem, natomiast wysłany e-mail był zdarzeniem.

Rys. 3 Schemat działania wzorca Obserwatora.

Czym jest schemat fabryk (Factory Pattern)? Jakie są jego zalety?

Tego schematu się wykorzystuje w sytuacji, w której chcemy tworzyć dużą ilość obiektów pochodzących od tego samego rodzica, bądź implementujących ten sam interfejs. Przydatny jest wtedy , gdy tworzenie obiektu jest kompleksową sytuacją, przykładowo mamy do wyboru bardzo dużą ilość obiektów, lub jesteśmy zmuszeni podać dużą ilość argumentów do konstruktora. Dzięki temu wzorcowi jesteśmy w stanie uprościć kreację obiektów oraz stworzyć jedną fabrykę, która będzie odpowiadała za kreację naszych obiektów. Implementacja tego wzorca przebiega w następujący sposób:

– grupujemy klasy, które implementują dany interfejs (bądź dziedziczą po jednej klasie);
– tworzymy klasę Factory, w której tworzymy metodę (metody) pozwalające na zwrócenie danego obiektu implementującego dany Interfejs bądź dziedziczący po danej klasie;
– tworzymy obiekt Factory i wykorzystujemy jego metody, aby otrzymać żądany obiekt.

Wszystko jest wytłumaczone kodowo na rysunkach poniżej:

Rys. 4 Klasy użyte w obrazku nr. 5
Rys. 5 Wykorzystanie Factory Pattern.

Czym są Beany? (To pytanie nie dotyczy ściśle wzorców projektowych, aczkolwiek umieściliśmy je tutaj, aby lepiej wytłumaczyć następny wzorzec)

Beanami się nazywa podstawowe obiekty wykorzystywane do podawania danych pomiędzy poszczególnymi częściami aplikacji. Ich budowa jest dosyć standardowa – składają się z prywatnych pól przechowujących konkretne dane pustego konstruktora. Zazwyczaj jedyne metody, jakie posiadają, to są gettery oraz settery. Ich wariacje wykorzystuje się przykładowo we frameworku Spring (Spring beans), jako obiekty którymi zarządza framework.

Czym jest wzorzec DAO? (DAO pattern)

Wzorzec DAO (Data Access Object) służy do utworzenia abstrakcyjnej warstwy rozdzielającej logikę biznesową oraz dostęp do bazy danych. Zazwyczaj klasa DAO implementuje interfejs, który zawiera wszystkie operacje wykonywane na obiekcie z bazy danych (operacje typu CRUD – create, retrieve, update, delete). Sama logika biznesowa (np. Kontroler) wykorzystuje metody zdefiniowane w interfejsie (nie mając pojęcia o ich konkretnej implementacji) do działania na bazach danych. Dzięki temu, jeżeli dokonane zostaną jakiekolwiek zmiany na sposobie pozyskiwania danych (np. zmieni się tabela bądź zapytanie), logika biznesowa pozostanie bez zmian. Do przekazywania danych pomiędzy poszczególnymi poziomami aplikacji wykorzystywane są wcześniej zdefiniowane beany, np. podczas kreacji rekordu w bazie danych podajemy do metody tworzącej (np. FakturyDAO.utworzFakture()) beana odpowiadającego za obiekt w bazie, natomiast przy operacjach pozyskiwania danych (np. FakturyDao.getInvoicesList()) otrzymujemy listę Beanów (InvoiceBean), odpowiadających poszczególnym rekordom z bazy danych.

Rys. 6 Prosty schemat działania wzorców DAO.

Czy jesteś w stanie rozwinąć akronim SOLID? Czego on dotyczy?

SOLID dotyczy zasad projektowania aplikacji według pięciu podstawowych zasad:

S – Single Responsibility Principle (SRP), zasada jednej odpowiedzialności,
O – Open Closed Design Principle (OCD), Zasada otwarte – zamknięte,
L – Liskov Substitution Principle (LSP), zasada podstawienia Liskov,
I – Interface Segregation Principle (ISP), zasada segregacji interfejsów,
D – Dependency Inversion Principle (DIP), zasada odwrócenia zależności.

Czym jest wzorzec Builder? Za co odpowiada?

Ten wzorzec powstał w odpowiedzi na problemy powstające przy kreacji obiektów przez wzorzec fabryk w przypadku, gdy tworzony obiekt posiadał wiele atrybutów. Jest to kolejny wzorzec zajmujący się kreacją obiektów w Javie.

Główną ideą przyświecającą jego powstaniu jest założenie, aby oddzielić kreację skomplikowanego obiektu od jego reprezentacji. Oznacza to, że ten sam proces konstrukcji może stworzyć różne reprezentacje danego obiektu. Metaforą tego założenia może być proces zamawiania hamburgera w porządnej restauracji. Każdy hamburger składa się z bułki, mięsa, dodatków oraz sosu. Nie ważne jest czy wybieramy bułkę pszenną czy grahamkę, czy sos Barbeque czy majonezowy – proces tworzenia tego burgera zawsze pozostaje taki sam.

Na rysunku poniżej doskonale widać jak może wyglądać taki wzorzec:

Rys. 7 Przykład klas używanych przez Builder’a
Rys. 8 Przykładowe użycie wzorcu Builder

Jaka jest różnica pomiędzy wzorcem fabryk (Factory) a abstrakcyjnych fabryk (Abstract Factory)?

Oba wzorce są klasyfikowane jako wzorce kreacyjne, pozwalające oddzielić użytkownika od skomplikowanego procesu kreacji obiektów. Istnieje jedna ważna różnica pomiędzy tymi dwoma wzorcami – wzorzec fabryk odpowiada za tworzenie określonych obiektów, natomiast abstrakcyjne fabryki pozwalają na łatwy sposób inicjalizacji potrzebnych nam fabryk. Abstrakcyjne Fabryki jest to po prostu kolejny poziom schematu otrzymywania określonych obiektów – łatwo jest to zobaczyć na poniższym rysunku:

Rys. 9 Schemat działania fabryk oraz abstrakcyjnych fabryk

Mamy nadzieję, że powyższy artykuł przybliżył Wam tematykę wzorców projektowych. Przedstawiliśmy Wam podstawy najważniejszych wzorców, tak abyście nie tylko mogli odpowiedzieć na pytania związane z nimi podczas rozmowy kwalifikacyjnej, ale również abyście mieli podstawy do zgłębienia wiedzy na ich temat samodzielnie. Jeżeli macie jakieś pytania – dajcie znać w komentarzu, a na pewno postaramy się na nie odpowiedzieć. Do zobaczenia w następnym artykule!

Następna część: Rozmowa kwalifikacyjna z Javy? Żaden problem! Cz. VI (Spring)

Autor: Marek Makuch

Oryginalny wpis pojawił się na naszym blogu w lipcu 2018r.

logo IT-Leaders

IT-Leaders.pl to pierwsza w Polsce platforma łącząca Specjalistów IT bezpośrednio z pracodawcami. Anonimowy, techniczny profil i konkretnie określone oczekiwania finansowe to tylko niektóre z cech wyróżniających platformę. Zarejestruj się i zobacz jak Cię widzi pracodawca.

Comments (4)

  1. Paweł

    Punkt 5, na pierwszym screenie jest mały błąd, Stringi porównujemy .equals() 🙂

Comments are closed.