Akka podstawy część 4 – Akka stany

Aktorzy w zależności od kontekstu, od tego co robią, mogą zmieniać swoje stany i zachowanie.

Pokażę teraz jak się tym zająć.

Chciałbym napisać aktora, który będzie … jadł 😉
Aktor to zwierze (np. krowa). Aby krowa nam dała wołowinę (mniam!), musimy ją nakarmić 10 razy. Po 10 razach, krowa ma iść do rzeźni i zamienić się w smaczne steki 🙂
Każda krowa ma „pojemność żołądka” równą 5. Gdy brzuszek ma pełen, to chce spać, i będzie spała, aż jej brzuszek będzie pusty. Wtedy znowu będzie głodna 🙂

No to napiszmy to.

Będę pisał w wersji dla Java 8 z użyciem AbstractActor’a.

Wszystko oczywiście na github – https://github.com/najavie/akka-eatingActor

Użyłem projektu mvn, aby nie bawić się activatorem.

Aktor

Oto aktor – zwierzę:

 

OK, nie jest to już takie proste.

Jedną z zalet programowania funkcyjnego, jest możliwość przypisania pod zmienną funkcji.

Przeanalizujmy ten przykład.

Najlepiej rozpocząć czytanie tego kodu od końca – od metody receive w konstruktorze –
Mamy tam tylko jednego matchera – jeśli przyjdzie wiadomość o treści „start”, nasz aktor wejdzie w stan – hungry. Robi się to w sposób jaki pokazałem. Pobieramy kontekst aktora za pomocą metody context() i mówimy mu, żeby stał się … głodny. hungry jak spojrzycie na definicję to zmienna, która jest tak na prawdę funkcją, która ma logikę własnego ReceiveBuilder’a.

Reasumując – zabawa ze stanami polega na:

  • Ustaleniu stanu aktora
  • Implementacji zachowania (funkcji) danego stanu
  • przekazaniu stanu aktora do kontekstu, a co za tym idzie przekazanie odbioru wiadomości do innej logiki.

Do każdego stanu aktora dodałem jeszcze funkcję – otherAction.

Funkcja otherAction to obsluga innych wiadomości.  Są one wspólne dla każdego stanu, dlatego umieściłem je jako osobne pola. Popatrzcie jakie to daje możliwości ! Możemy dynamicznie przypisywać logikę do aktorów, zmieniać ją w trakcie pracy systemu, jeśli tylko nastąpią jakieś warunki. W moim przypadku jeśli aktor zje pięć razy, stanie się najedzony i będzie chciał iść spać, do czasu aż jego poziom głodu nie spadnie do zera. Logika bardzo prosta, a gdy się zrozumie, że funkcjonalność to zmienna, którą dodajemy do stanu to nagle dostajemy w swoje ręce na prawdę bardzo duże możliwości implementacyjne !

Ok… to jeszcze… One ring to rule them all !

Stworzę zarządcę. Kolejnego aktora, który będzie pilnował zwierząt i jeśli zjedzą wystarczająco… ubije je…

Oto zarządca:

 

Ok, tutaj pojechałem trochę po bandzie 😉

Użyłem metody preStart() – jeśli chcemy coś wykonać przed uruchomieniem aktora – to jest fajne miejsce. W nim umieściłem zgrupowanie aktorów – zwierząt w mapę.

Jak zabić aktora? Twórcy Akki mają fajne poczucie humoru – aby zabić aktora, trzeba mu wysłać … truciznę 😉 PoisonPill 🙂 Jeśli wyślemy aktorowi wiadomość w postaci PoisonPill, aktor zakończy swój żywot… zmieni się jego stan na Terminated, i jeśli wyślemy do niego wiadomość… Cóż… jako zadanie domowe, sprawdźcie sami 🙂

Cała reszta kodu jest chyba w miarę oczywista. Kilka PartialFunctions, które porządkują kod, prosta logika sprawdzania, ile zwierze zjadlo, i ewentualna…śmierć…

Jak zauważyliście, nie użyłem żadnego routera. W przypadku gdy chcę trzymać stan ilości pochłoniętego przez aktora jedzenia, wygodniej i prościej było mi użyć zwykłej mapy.

To już jest nieco bardziej zaawansowany przykład jak używać aktorów, jak można dokonywać z nimi interakcji. W praktyce, obojętnie czy użyjemy cool Java 8 features, czy zwykłego UntypedActora używanie aktorów sprowadza się do napisania logiki obsługującej różne zdarzenia, ewentualnie na podstawie tych zdarzeń zmienić stan aktora i tyle 🙂

Zostało nam jeszcze wprawienie całego systemu w ruch:

Tworzę jednego zarządcę, mówię mu start… a resztą zajmuje się już Akka… 🙂

 

 

 

 

«
»