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 – Chain of Responsibility
  • Programowanie
  • Wszystko

Wzorce projektowe – Chain of Responsibility

Jakub Raczkowski 2 lutego 2024

Źródło obrazka: Pixels.com (aut. Hans Jankowski)

Bohater dzisiejszego wpisu z jednej strony potrafi wyglądem przypominać Dekoratora. Z drugiej jego zachowaniu bliżej do wzorca Stan. Poznajcie: Łańcuch odpowiedzialności!

Wyobraźmy sobie mały bar w którym można się najeść i napić. Siedzi tam sobie klient i popija kapuczynę przeglądając telefon. W pewnej chwili próbując chwycić za filiżankę omyłkowo ją potrącił i wylał napój. Zauważył to sprzedawca i ruszył na miejsce z mopem.

Ale to nie wszystko. Klient zaczyna się awanturować, że utrata kawy to nie jego wina, że kubek był mokry i mu się wyślizgnął. Żąda nowej kapuczyny, a po odmowie ze strony sprzedawcy mówi, że chce się widzieć z kierownikiem.

Przychodzi wezwany kierownik i zaczyna się wymiana zdań. Klient krzyczy, a menedżer próbuje go uspokoić. W pewnym momencie dochodzi do gróźb, zaczyna się szamotanina. W tym miejscu do gry wchodzi policjant po służbie, który do tej pory tylko obserwował sytuację znad swojej herbaty.

Źródło: film Pulp Fiction

Przytoczona historia obrazuje w jaki dokładnie sposób działa i kiedy się przydaje wzorzec Łańcuch. Domyślnie łączy on klasy z tym samym interfejsem i przepuszcza obiekt klienta przez ich kolejne metody. Czasami już pierwsza załatwi potrzebę obiektu, a czasem dopiero ta ostatnia (albo żadna).

Jeśli problemem byłaby tylko plama na podłodze, to wystarczył by sam sprzedawca z mopem, ale kiedy pojawiły się groźby i przemoc, potrzebna była policja.

Gdyby zależało wam na przykładach bardziej związanych z programowaniem mógłbym wymienić filtr antyspamowy na kontach mailowych. Kiedy przychodzi nowa poczta, najpierw sprawdza się czy to nie spam. Potem sprawdza się czy nadawca nie jest zapisany w naszych kontaktach – jeśli tak to mail leci do folderu Ważne. I tak dalej.

Nie każdy spam jest zły.

We wstępniaku mówiłem, że składnia Łańcucha wygląda trochę jak ta z Dekoratora, spójrzcie sami:

Mail mail = new Mail(); 
mail.setFilter(new SpamFilter(new RegularMail(new ImportantMail(null))));

Poczta przechodzi przez Spam, potem przez Zwykłe Wiadomości, potem przez Ważne. Na każdym z tych filtrów może się zatrzymać. Spójrzmy jaka jest oficjalna definicja Łańcucha:

Łańcuch odpowiedzialności – umożliwia dynamiczne dodawanie i usuwanie procedur obsługi poprzez zmianę elementów lub kolejności łańcucha. Ponadto upraszcza obiekt, ponieważ nie wymaga utrzymywania informacji o strukturze łańcucha – separuje nadawcę żądania od jego odbiorców.

Rusz głową! Wzorce projektowe

Jeśli zaś chodzi o strukturę to ważne aby każde z ogniw Łańcucha posiadało informację o jego następcy – do kogo się zwrócić jeśli samemu nie uda się sprostać potrzebom obiektu. Wyglądem kodu przypomina to nieco wzorzec Stan i jego odniesienia do kolejnych stanów. Pamiętajmy jednak, że „stany” to hermetyzowane zachowania jednego obiektu, natomiast w Łańcuchu mamy metody różnych klas przez które ma przejść obiekt (albo się na którejś zatrzymać).

Ale po kolei…

To co lubię w grach cRPG to uczucie zagubienia i swojej maleńkości wobec wrogów na początku rozgrywki. Potem poznajemy ten świat, zdobywamy doświadczenie i podchodzimy do coraz to trudniejszych wyzwań. Jeśli nie zaniedbaliśmy rozwoju, to do końcowego bossa wkraczamy bez jakiejkolwiek spiny i tylko jak już jest po wszystkim przypominamy sobie o całej torbie mikstur siły, niewrażliwości i szybkości jakie chomikowaliśmy na czarną godzinę, która nigdy nie nadeszła.

Równocześnie nienawidzę, kiedy gra wymusza skalowanie przeciwników do naszego poziomu. Niby, że dla balansu rozgrywki, ale chrzanię taką sytuację, kiedy zwykły szczur nagle ma 200 punktów życia, tylko dlatego bo podekspiliśmy. Już wolę żeby było jak w Gothicu – w czasie wypełniania ostatnich questów biegałem przez mapę jak szalony i tylko od niechcenia rozpłatywałem ścigające mnie Zębacze – potwory, które brały mnie na hita przez pierwsze godziny zabawy.

Zębacz (Gothic 1)

W takich realiach naturalnym jest, że czasami zawędrujemy za daleko i natrafimy na przeciwnika, który położy nas jednym machnięciem łapy. Wtedy korzystamy z metody loadGame() i już wiemy z kim nie należy zadzierać… póki nie podniesiemy poziomu i nie kupimy lepszego miecza.

Na bazie powyższego stworzyłem kawałek kodu (tutaj), który pokazuje jak owa sytuacja wyglądałaby ze wzorcem Łańcuch:

Tym razem postawiliśmy na brutalną siłę barbarzyńcy.

Widzimy, że nasz barbarzyńca z pierwszym poziomie nie stanowi wyzwania nawet dla Goblina, ale z kolejnymi levelami udaje mu się pokonywać coraz to mocniejszych wrogów, aż na placu boju pozostał tylko on. Zwycięstwo!

public void defend(Barbarian barbarian) {
            if (barbarian.level <= 3) System.out.println("Goblin: Dam mu radę sam!");
            else {
                System.out.println("Goblin: Potrzebuję pomocy!");
                barbarian.setEnemy(nextEnemy);
            }
        }

Powyżej widzimy metodę Goblina, która sprawdza czy samemu da radę obiektowi barbarzyńcy, a jeśli nie to wysyła go do nextEnemy wstrzykniętego wcześniej do swojego konstruktora.

Tak wygląda to w dynamicznej implementacji, kiedy kolejne ogniwa wybierane są w czasie tworzenia łańcucha:

Barbarian barbarianLv1 = new Barbarian(1);
        barbarianLv1.setEnemy(new Goblin(new OrcWarlord(new TrollKing(null))));

Możemy też nieco usztywnić architekturę, tak jak to zrobiłem w drugiej, rozbudowanej wersji kodu (tutaj). Wtedy następny przeciwnik jest już na stałe ustawiony u poprzednika:

Heros na pierwszym poziomie położył Goblina, ale nie dał rady Orkowi.
Na 4 levelu dochodzi skill ofensywny „Atak z wyskoku” dzięki któremu bohaterowi udało się dostać do bossa.
Na 7 levelu mamy kolejną umiejętność: 'Unik’ – tylko dzięki temu udało się pokonać Króla Trolli.

ITCandidateEvaluator

Bez skruchy przyznaję, że wzorzec Chain of Responsibility wybrałem do opisania właśnie dlatego bo miałem fajny pomysł na jego zakodowanie z udziałem Króla Trolli i jego przydupasów. Pisanie tego o ósmej rano, ze stygnącą kawą obok monitora dało mi sporo frajdy – nawet kiedy Chat GPT ocenił to na słabą próbę podejścia do wzorca (dlatego powstała jeszcze krótsza, bardziej „książkowa” wersja kodu).

Mimo osobistej sympatii do Łańcucha nie widzę jednak wiele możliwości umieszczenia go u siebie w kolejnym projekcie. Niby genialnie nadałby się do logowania wyjątków o różnych poziomach ważności, ale po co będę sam to pisał, skoro logger log4j zrobi to za mnie?

Tyle w temacie wzorców prostych. W kolejnym odcinku przerobimy jeszcze Model-View-Controller i chwilowo dajemy sobie na wstrzymanie z tą serią.

Tags: design patterns programming

Continue Reading

Previous: Wzorce projektowe – Builder
Next: Wzorce projektowe – MVC

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
Netflix odpala nową funkcję, która da użytkownikom więcej władzy
Tanie iPhone'y i Samsungi w nowym sklepie Orange
Fani Androida mają powód do radości. Wraca wsparcie uwielbianej funkcji
Wielkie nieporozumienie wokół nowego iPhone’a. Zobaczcie to, zanim zaczniecie krytykować
Chiny przejmują legendarny oddział Sony. Koniec ery
Tak chcemy wyjaśnić napięcie Hubble'a. Lepszej metody dotąd nie było
Netflix odkrywa karty o premierach. Wiemy, co pokaże na dniach
A co powiesz na ładowanie... laserem? Badacze już to testują
ChatGPT zabierze nasze pieniądze? Nowy pomysł jeszcze gorszy niż reklamy
To najmniejsza myszka na świecie. Użyjesz jej wszędzie
Ta aplikacja to „centrum dowodzenia” każdego miłośnika podróży
Kaufland zaszalał. Rozchwytywany sprzęt Parkside trafił na półki
O tych nowościach w Windows 11 jest dziwnie cicho. A szkoda
Microsoft szykuje rewolucję. Skorzystasz, jeśli obejrzysz reklamy
Te zestawy LEGO za moment znikną z rynku. Wiecie, co to oznacza?
To już ostatni dzwonek! Skorzystaj za darmo, zanim Apple to wyłączy
Masz uczulenie na sierść psa? Z tym nic ci nie grozi
Prawdziwa bomba od T-Mobile - klienci Heyah będą zachwyceni!
Garmin, Samsung i Apple na celowniku. Te zegarki mogą zniknąć z rynku
Łatwiej zmienisz przeglądarkę na iPhonie. Wystarczy jedna opcja
To by było na tyle, jeśli chodzi o możliwość ugody
Ocalić od zapomnienia
Ostatni kwant
ALH 84001 – meteoryt, o którym mówiono nawet w Białym Domu
HESS zarejestrował kosmiczny elektron o niespotykanej energii [Phys. Rev. Lett.]
Matka ciemnej materii – recenzja biografii “Vera Rubin. Życie”
Satelita, który zerwał się ze smyczy
Wiadomość od Carla Sagana do przyszłych eksploratorów Marsa
Ile najdłużej może trwać zaćmienie Słońca?
Nowa największa liczba pierwsza ma ponad 41 milionów cyfr [GIMPS]
30 lat konsoli PlayStation – Odcinek #130
Omawiamy serię The Walking Dead (gość: Stary Gracz)
Nikt nie potrzebuje cienkich smartfonów – Odcinek #129
To ostatni dzwonek na kolekcjonowanie gier i filmów
Najlepsza relacja z PGA 2025 (Poznań Game Arena)
Bumblebee wśród klawiatur. Marvo Meqa 80W – recenzja
Pierwsze spotkanie z Omoda 7 Super Hybrid
Logitech MX Master 4, Wednesday, 1670 sezon 2 – Odcinek #128
Tani pad, który chciał być jak DualSense. Test Monka Contra GT-96
Secret Service i prasa komputerowa w Polsce – Odcinek #127

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.