Implementácia jednoduchých stavových strojov s využitím Java Enums

1. Prehľad

V tomto tutoriáli sa pozrieme na State Machines a na to, ako ich možno implementovať v Jave pomocou Enums.

Vysvetlíme tiež výhody tejto implementácie v porovnaní s použitím rozhrania a konkrétnej triedy pre každý štát.

2. Java Enums

Java Enum je špeciálny typ triedy, ktorý definuje zoznam konštánt. Toto umožňuje typovo bezpečná implementácia a čitateľnejší kód.

Ako príklad predpokladajme, že máme softvérový systém HR, ktorý dokáže schvaľovať žiadosti o dovolenku podané zamestnancami. Túto žiadosť posúdi vedúci tímu, ktorý ju postúpi vedúcemu oddelenia. Vedúci oddelenia je osoba zodpovedná za schválenie žiadosti.

Najjednoduchší výčet, ktorý obsahuje stavy žiadosti o dovolenku, je:

public enum LeaveRequestState {zadané, eskalované, schválené}

Môžeme sa odvolať na konštanty tohto výčtu:

Stav LeaveRequestState = LeaveRequestState.Submitted;

Enums môžu obsahovať aj metódy. Môžeme napísať abstraktnú metódu do enumu, ktorý prinúti každú inštanciu enum implementovať túto metódu. To je veľmi dôležité pre implementáciu štátnych strojov, ako uvidíme ďalej.

Pretože Java enums implicitne rozširuje triedu java.lang.Enum, nemôžu rozšíriť inú triedu. Môžu však implementovať rozhranie, rovnako ako každá iná trieda.

Tu je príklad enumu obsahujúceho abstraktnú metódu:

public enum LeaveRequestState {Zadané {@Override public String responsiblePerson () {návrat "Zamestnanec"; }}, Escalated {@Override public String responsiblePerson () {return "Vedúci tímu"; }}, Schválené {@Override public String responsiblePerson () {návrat "Vedúci oddelenia"; }}; verejný abstrakt Reťazec zodpovednýPerson (); }

Všimnite si použitie bodkočiarky na konci poslednej konštanty výčtu. Bodkočiarka je povinná, ak máme jednu alebo viac metód sledujúcich konštanty.

V tomto prípade sme prvý príklad rozšírili o a zodpovedná osoba() metóda. Toto nám hovorí osoba zodpovedná za vykonanie každej akcie. Pokiaľ sa teda pokúsime skontrolovať osobu zodpovednú za Eskalované štáte, dá nám „Vedúci tímu“:

Stav LeaveRequestState = LeaveRequestState.Escalated; assertEquals ("Vedúci tímu", state.responsiblePerson ());

Rovnakým spôsobom, ak skontrolujeme, kto je zodpovedný za schválenie žiadosti, poskytne nám to „Vedúci oddelenia“:

Stav LeaveRequestState = LeaveRequestState.Approved; assertEquals ("Vedúci oddelenia", state.responsiblePerson ());

3. Štátne automaty

Stavový stroj - nazývaný tiež konečný stavový automat alebo konečný automat - je výpočtový model používaný na zostavenie abstraktného automatu. Tieto stroje môžu byť v danom čase iba v jednom stave. Každý stav je stavom systému, ktorý sa mení na iný stav. Tieto zmeny stavu sa nazývajú prechody.

V matematike sa to môže komplikovať pomocou diagramov a notácií, ale pre nás programátorov je to oveľa jednoduchšie.

Štátny vzor je jedným zo známych dvadsiatich troch návrhových vzorov GoF. Tento vzor si požičiava koncept z modelu v matematike. Umožňuje objektu zapuzdriť rôzne chovania pre ten istý objekt na základe jeho stavu. Môžeme naprogramovať prechod medzi stavmi a neskôr definovať samostatné stavy.

Aby sme koncept lepšie vysvetlili, rozšírime náš príklad žiadosti o opustenie o implementáciu stroja stavu.

4. Enums as State Machines

Zameriame sa na enumovú implementáciu štátnych strojov v Jave. Sú možné ďalšie implementácie, ktoré si v nasledujúcej časti porovnáme.

Hlavným bodom implementácie stavového automatu pomocou enumu je to nemusíme riešiť výslovné nastavenie štátov. Namiesto toho môžeme poskytnúť iba logiku spôsobu prechodu z jedného stavu do druhého. Poďme sa ponoriť priamo do:

public enum LeaveRequestState {Zadané {@Override verejné LeaveRequestState nextState () {návrat Escalated; } @Override public String responsiblePerson () {návrat "Zamestnanec"; }}, Escalated {@Override public LeaveRequestState nextState () {return Approved; } @Override public String responsiblePerson () {návrat "Vedúci tímu"; }}, Schválené {@Override public LeaveRequestState nextState () {vrátiť toto; } @Override public String responsiblePerson () {návrat "Vedúci oddelenia"; }}; verejný abstrakt LeaveRequestState nextState (); verejný abstrakt Reťazec zodpovednýPerson (); }

V tomto príklade prechody stavových strojov sa implementujú pomocou abstraktných metód enum. Presnejšie pomocou nextState () pri každej konštante enum určíme prechod do ďalšieho stavu. V prípade potreby môžeme realizovať aj a previousState () metóda.

Ďalej uvádzame test na kontrolu našej implementácie:

Stav LeaveRequestState = LeaveRequestState.Submitted; state = state.nextState (); assertEquals (LeaveRequestState.Escalated, state); state = state.nextState (); assertEquals (LeaveRequestState.Approved, state); state = state.nextState (); assertEquals (LeaveRequestState.Approved, state);

Žiadosť o dovolenku začíname v Predložené počiatočný stav. Potom overíme prechody stavu pomocou nextState () metóda, ktorú sme implementovali vyššie.

Poznač si to odkedy Schválené je konečný stav, nemôže dôjsť k nijakému inému prechodu.

5. Výhody implementácie stavových strojov s Java Enums

Implementácia štátnych strojov s rozhraniami a implementačnými triedami môže predstavovať značné množstvo kódu na vývoj a údržbu.

Pretože výčet Java je vo svojej najjednoduchšej forme zoznamom konštánt, môžeme na definovanie našich stavov použiť výčet. A keďže enum môže obsahovať aj správanie, môžeme na zabezpečenie implementácie prechodu medzi stavmi použiť metódy.

Mať všetku logiku v jednoduchom výčte umožňuje čisté a priame riešenie.

6. Záver

V tomto článku sme sa pozreli na štátne stroje a na to, ako je možné ich implementovať v Jave pomocou Enums. Dali sme príklad a otestovali sme ho.

Nakoniec sme tiež diskutovali o výhodách použitia enums na implementáciu stavových strojov. Ako alternatívu k rozhraniu a implementačnému riešeniu poskytuje enums čistejšiu a ľahšie pochopiteľnú implementáciu štátnych strojov.

Všetky útržky kódu uvedené v tomto článku ako vždy nájdete v našom úložisku GitHub.


$config[zx-auto] not found$config[zx-overlay] not found