Skip to content

Witaj w Świecie Jutra!

  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
  • Home
  • Wszystko
  • Wzorce projektowe – Abstract factory & Factory method
  • Programowanie
  • Wszystko

Wzorce projektowe – Abstract factory & Factory method

Jakub Raczkowski 20 stycznia 2024

Bing AI

Dzisiejszy odcinek jest sponsorowany przez Hermetyzacja z.o.o. Dołącz do naszej idei, a już nigdy nie będziesz musiał mieć jakiejkolwiek styczności z innymi klasami w realu! Po co brudzić sobie ręce produkcją obiektów skoro możesz to zlecić naszym fabrykom?

Wniosek płynący z opisu wzorca Dekorator w poprzednim wpisie mógłby brzmieć następująco:

Dziedziczenie jest be, interfejsy są cacy.

Coś w tym jest, ale nie popadajmy w przesadę. O ile sztywna struktura klasowa może się okazać problemem przy późniejszej rozbudowie aplikacji, o tyle w schludny sposób deklaruje hierarchię klas i upraszcza kod. Mimo to pisząc super- i podklasy warto zadbać o wspomnianą we wstępniaku hermetyzację czyli odseparowanie elementów mających tendencję do zmian od reszty kodu.

Ale po czym poznamy takie elementy? Cóż, jedną z wskazówek może być słówko:

new

W programowaniu obiektowym musimy tworzyć nowe obiekty, to fakt. Abstrakcja klas i interfejsów pomaga w ułożeniu dobrze działającej struktury, ale koniec końców musimy i tak stworzyć jakiś obiekt, nadać mu pożądany stan i wywołać jego metody. Tylko, że można to zrobić na rympał, a można to zrobić z głową – z pomocą fabryki.

Kadr z filmu „Shrek 2”.

Tym razem zajmiemy się jednocześnie dwoma wzorcami, które stoją blisko siebie, zazwyczaj są używane razem i jednocześnie tak często są ze sobą mylone, że grzechem byłoby je rozdzielać na dwa artykuły. A są to:

Abstract Factory oraz Factory Method

Dwa wzorce z fabryką w nazwie. Znaczy – muszą coś produkować. A co? Spytajmy podręcznik:

Wzorzec Metoda Fabrykująca definiuje interfejs pozwalający na tworzenie obiektów, ale pozwala klasom podrzędnym decydować, jakiej klasy obiekt zostanie utworzony. Wzorzec MF przekazuje odpowiedzialność za tworzenie obiektów do klas podrzędnych.

Wzorzec Fabryka Abstrakcyjna dostarcza interfejs do tworzenia całych rodzin spokrewnionych lub zależnych od siebie obiektów bez konieczności określania ich klas rzeczywistych.

Rusz Głową! Wzorce projektowe.

W moim pierwszym projekcie stworzyłem klasę SquareFactory posiadającą jedną statyczną metodę createColoredSquares(…) która tworzyła dla mnie listę z żądaną ilością kwadracików w wybranym kolorze:

public static List<Square> createColoredSquares(int amount, SquareColor color) {
        List<Square> coloredSquares = new ArrayList<>();
        for (int i = 0; i < amount; i++) {
            String name = color.name().toLowerCase() + i;
            Square square = new Square(color, name);
            coloredSquares.add(square);
        }
        return coloredSquares;
    }

Nie był to jednakże przykład wykorzystania ani Factory Method ani Abstract Factory, a co najwyżej idiom czyli taki mini wzorzec, który może ograniczać się do jednej linijki kodu, która już na pierwszy rzut oka jest zrozumiała. Do pełnego wzorca trochę zabrakło.

Ale po kolei…

Jedną z najbardziej skutecznych, a jednocześnie najłatwiejszych taktyk w grach na silniku Infinity Engine (czyli takich jak Wrota Baldura albo Icewind Dale) jest przywoływanie stworzeń, tzw. „summonów” aby walczyły za nas.

Kluczem jest posiadanie w drużynie klas, które mają czar przyzwania – takich jak np. czarodziej, kleryk albo druid. Wtedy w zależności od tym kim kierujemy, możemy liczyć na powiększenie naszej drużyny o kilka wilków, żywiołaka ognia albo – na najwyższych poziomach profesji – o najprawdziwszego anioła („Devę”)!

Deva

Maksymalna ilość summonów jednocześnie to 5. Niektóre czary przyzywają od razu kilku słabszych pomagierów, z kolei inne skupiają się na przywołaniu jednego, ale za to kozaka. Mając całą piątkę takich jednorazowych minionów wysyłamy ich w rejon mapki gdzie wcześniej zauważyliśmy wrogów i czekamy patrząc na logi w dzienniku. Summony, tak jak wrogowie, mają swoje skrypty więc nie musimy im wydawać żadnych rozkazów – atakują najbliższego wroga póki nie padnie, albo same nie zginą. Kiedy akcja zelżeje wpadamy na pobojowisko swoją drużyną, likwidujemy niedobiktów i zbieramy fanty.

Klimatyczne? W żadnym wypadku!
Skuteczne? Jeszcze jak!

A teraz pomyślmy – jak najlepiej tworzyć obiekty summonów mając na uwadze, że zależą one od klasy postaci i jej poziomu oraz użytego zaklęcia? A do tego są to elementy jednorazowe, bez znaczenia dla fabuły.

Tego się nie tyka, to zrobiła fabryka.

Należy posłużyć się fabrykami, które odseparują takie szybkie tworzenie obiektów (gdzie liczy się ilość, a nie jakość) od reszty kodu. Spójrzcie poniżej, cały kod znajdziecie tutaj.

Druid przyzywa 3 wilki, a czarodziej jednego żywiołaka.
„Summoner” to prosty interfejs z jedną metodą. Bez znaczenia dla dzisiejszej lekcji.

Mamy dwie klasy: Wizard oraz Druid, z tym samym interfejsem: Summoner. Nie tworzyłem tutaj osobnych zaklęć aby nie komplikować kodu. Każda klasa korzysta z metody summon(), ale z wykorzystaniem własnej fabryki. Obie zaimplementowane fabryki są podklasami abstrakcyjnej SummonFactory (czyli naszej ABSTRACT FACTORY).

Fabryka i metoda fabryczna na jednym screenie. Zazwyczaj występują razem, ale jedna bez drugiej też może się zdarzyć.

Fabryka ta posiada dwie metody – jedna (summonAllies) jest już zaimplementowana i „dzieci” klasy używają jej dokładnie w takiej formie, bez przesłaniania. Natomiast druga (createSummons) jest abstrakcyjna i to od podklas zależy co tam dokładnie się znajdzie.

Podklasy fabryki, dla czarodzieja i druida, implementują własne wersje metody fabrycznej.

Podsumowując. Abstract factory (AF) zajmuje się tworzeniem rodziny spokrewnionych obiektów – otrzymujemy listę „summons” tylko z obiektami implementującymi owy interfejs. Factory method (FM) to pusta metoda w tej fabryce – to od podklas zależy w jaki sposób zostanie zaimplementowana.

Powyższy opis wciąż może wydawać się niejasny, dlatego poratuję was jeszcze hintem:

AF musi odpowiadać na pytanie „ile obiektów dostaniemy?”, natomiast FM na „jakie dokładnie to będą obiekty?”.

W przytoczonym kodzie AF mówi, że dostaniemy listę z iluśtam przyzwańcami. A FM tłumaczy, że jeśli jesteśmy czarodziejem to dostaniemy żywiołaka, a jak druidem to wilki.

Przy okazji – przytoczony problem równie dobrze dałoby się rozwiązać wzorcem Strategia i tak ja to właśnie zrobiłem w swoim projekcie. Jak się teraz okazuje – trochę na opak, bo zgodnie z zasadą Strategia proponuje różne algorytmy do otrzymania konkretnych danych, a wzorce Fabryki specjalizują się w tworzeniu obiektów. Niby detal, ale wiele mówi innym programistom co się dzieje w danych klasach już na pierwszy rzut oka.

ITCandidateEvaluator

Abstract factory oraz Factory method przydają się szczególnie kiedy masowo tworzymy obiekty – czy to podczas kompilacji czy już w czasie działania programu. W moim przypadku pasuje do tego szablonu obiekt „KandydatDoPracy” (Candidate). Zakładając, że na daną ofertę dostaniemy ponad 100 zgłoszeń, z czego sporo odpadnie już na etapie przeglądania CV to i tak można liczyć na kilkanaście rozmów rekrutacyjnych co przekłada się na taką samą liczbę obiektów Candidate.

Sam obiekt kandydata nie będzie szczególnie skomplikowany. Na pewno musi mieć zmienne takie jak: imię i nazwisko, może jeszcze datę urodzenia. Przyda się ścieżka do pliku z CV. Ponadto mapa „punkty” z punktami otrzymanymi na każdym etapie rekrutacji oraz metoda calculatePoints() zawierająca algorytm wyliczający końcowy wynik.

I tu właśnie zaczynają się schody. No bo tak, mogę po prostu stworzyć klasę Candidate, ustawić wszystko na sztywno i mieć resztę w du… Ale potem może się okazać, że algorytm liczący punktację dla juniora może się różnić od tego dla seniora. I zmieniaj chłopie teraz te wszystkie przypadki użycia obiektu Candidate… Lepiej niech Candidate to będzie klasa abstrakcyjna po której dziedziczą Juniorzy, Midzi i Seniorzy. Albo nie, bo może kiedyś…

Sami widzicie – sprawę należy przemyśleć bardzo dokładnie. Jedno jest natomiast pewne:

Projekt jest rozwojowy, zadbam więc o odpowiednią hermetyzację, a to oznacza, że miejsce dla jakiejś fabryki na pewno się znajdzie.

Dziękuję za uwagę i zapraszam do następnego wpisu poświęconego wzorcowi Singleton.

Tags: design patterns programming

Continue Reading

Previous: Wzorce projektowe – Decorator
Next: Wzorce projektowe – Singleton

Related Stories

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025

Ze świata

  • Antyweb
  • Kwantowo
  • Dwóch po dwóch
Nowy iPhone rozładowywał się przez noc. Skuteczna okazała się tylko jedna procedura
To jeden z największych problemów na polu walki. Firma z USA wie, jak go rozwiązać
Zostawiasz ładowarkę w gniazdku? Sprawdź, ile prądu naprawdę zużywa
Nie działa Ci ChatGPT? W usługę trafiła poważna awaria
Xbox szuka sposobu na odbicie się od dna. Lekarstwem ma być ostatnia decyzja
Google Pixel 11a już bez tajemnic. Kilka kluczowych zmian
Garmin wydłuża czas pracy zegarków. Tę aktualizację warto pobrać
LEGO przygotowało prawdziwą ucztę dla kolekcjonerów. Ten zestaw zachwyca od pierwszego spojrzenia
Sony wyciska użytkowników PlayStation od lat. Dziw, że dopiero teraz zauważyliście
YouTube rozczarowuje użytkowników. Wszystkiemu winien nowy błąd
Śpisz z telefonem przy poduszce? Lepiej odłóż go w inne miejsce
Stworzył fizyczne wydania gier na Steama. Są dostępne na "kartridżach"
Złoto na strychu? Te stare telefony mogą być dziś warte fortunę
Thule EnRoute 12L – recenzja. Wypełnia lukę między nerką, a plecakiem podróżnym
HP blokuje nawet oryginalne tusze? Kontrowersje wokół aktualizacji drukarek narastają
"Polski ChatGPT" goni najlepszych. Jest świetny, ale ja nie kupuję w nim jednej rzeczy
Chcesz jeść mniej? Lepiej tak nie rób. Naukowcy obalili popularny mit
Spotify nadrabia zaległości. Potrzebna opcja trafi do aplikacji
Ta platforma VOD kpi sobie z Polaków. Nie tak to miało wyglądać
Garmin CIRQA na pierwszym zdjęciu. Premiera tuż za rogiem
SpudCell – syntetyczna komórka, która udaje życie
Mega upał, omega manipulacja
Coraz więcej dowodów, coraz mniej pewności
Matematyczno-restauracyjny dylemat Ryszarda
Silnik produkujący informacje zamiast spalin
Orzeczenie w sprawie En Arche v. Adam Adamczyk
To by było na tyle, jeśli chodzi o możliwość ugody z kreacjonistami
Ocalić od zapomnienia
Ostatni kwant
ALH 84001 – meteoryt, o którym mówiono nawet w Białym Domu
Tańszy Game Pass, droższy Steam Deck i Internet 0202122 – Odcinek #135
Elite Dangerous. Gra, z której odchodzi się po cichu
Gry zasługujące na adaptację filmową – Odcinek #134
Relacja z RePlay Fest 2026
Najlepsze intra i openingi w grach – Odcinek #133
AI, Star Trek, Rycerz Siedmiu Królestw, Festiwal dem na Steam Next Fest – Odcinek #132
Gry, filmy i seriale w 2025 i 2026 roku – Odcinek #131
30 lat konsoli PlayStation – Odcinek #130
Omawiamy serię The Walking Dead (gość: Stary Gracz)
Nikt nie potrzebuje cienkich smartfonów – Odcinek #129

To może cię zainteresować:

Mageege Moon104 – test niskoprofilowego mechanika
  • Sprzęt

Mageege Moon104 – test niskoprofilowego mechanika

11 marca 2025
Przebranżowienie cz.4
  • Programowanie

Przebranżowienie cz.4

27 lutego 2025
Smartfon Jutra
  • Sprzęt

Smartfon Jutra

15 lutego 2025
Czym jest Swagger?
  • Programowanie

Czym jest Swagger?

22 lipca 2024
  • Technologie jutra
  • Sprzęt jutra
  • Aplikacje jutra
  • Programowanie
  • Księga Drogi
  • Renowacja
  • Różności
  • Archiwum
  • Autor
Copyright © All rights reserved. | DarkNews by AF themes.