Návrhový vzor je šablóna, ktorá rieši bežne sa opakujúci problém pri návrhu softvéru.
Vzorec stavu je vzorec správania, ktorý umožňuje objektu zmeniť svoje správanie, keď sa zmení jeho vnútorný stav.
Tu sa dozviete, ako používať vzor stavu v TypeScript.
Čo je štátny vzor?
Stavový návrhový vzor úzko súvisí s konečným automatom, ktorý popisuje program, ktorý existuje v a konečný počet stavov v danom momente a v každom štáte sa správa inak.
Existujú obmedzené, vopred určené pravidlá – prechody – ktoré riadia ostatné stavy, do ktorých môže každý štát prejsť.
Pre kontext, v internetovom obchode, ak bola nákupná objednávka zákazníka „doručená“, nemožno ju „zrušiť“, pretože už bola „doručená“. „Doručené“ a „Zrušené“ sú konečné stavy objednávky a objednávka sa bude správať odlišne v závislosti od jej stavu.
Štátny vzor vytvorí triedu pre každý možný stav so správaním špecifickým pre daný stav obsiahnutým v každej triede.
Príklad štátnej aplikácie
Predpokladajme napríklad, že vytvárate aplikáciu, ktorá sleduje stavy článku pre vydavateľskú spoločnosť. Článok môže buď čakať na schválenie, môže byť navrhnutý autorom, upravený redaktorom alebo publikovaný. Toto sú konečné stavy článku, ktorý sa má publikovať; v rámci každého jedinečného štátu sa článok správa inak.
Pomocou stavového diagramu nižšie si môžete vizualizovať rôzne stavy a prechody aplikácie článku:
Pri implementácii tohto scenára v kóde by ste najprv museli deklarovať rozhranie pre článok:
rozhranieRozhranie článku{
výška(): neplatné;
návrh(): neplatné;
upraviť(): neplatné;
zverejniť(): neplatné;
}
Toto rozhranie bude mať všetky možné stavy aplikácie.
Ďalej vytvorte aplikáciu, ktorá implementuje všetky metódy rozhrania:
// Aplikácia
triedaČlánoknáradiaRozhranie článku{
konštruktér() {
toto.showCurrentState();
}súkromnéshowCurrentState(): neplatné{
//...
}verejnostiihrisko(): neplatné{
//...
}verejnostinávrh(): neplatné{
//...
}verejnostiupraviť(): neplatné{
//...
}
verejnostizverejniť(): neplatné{
//...
}
}
Súkromné showCurrentState metóda je úžitková metóda. Tento tutoriál ho používa na zobrazenie toho, čo sa deje v jednotlivých štátoch. Nie je to povinná súčasť štátneho vzoru.
Spracovanie prechodov stavov
Ďalej budete musieť zvládnuť prechody stavov. Spracovanie prechodu stavu vo vašej aplikačnej triede by si vyžadovalo veľa podmienené príkazy. Výsledkom by bol opakujúci sa kód, ktorý je ťažšie čítať a udržiavať. Ak chcete vyriešiť tento problém, môžete delegovať logiku prechodu pre každý stav na jeho vlastnú triedu.
Pred napísaním každej triedy stavu by ste mali vytvoriť abstraktnú základnú triedu, aby ste zabezpečili, že každá metóda volaná v neplatnom stave vyvolá chybu.
Napríklad:
abstraktnétriedaČlánok ŠtátnáradiaRozhranie článku{
pitch(): ArticleState {
hodiťNovýChyba(„Neplatná operácia: Úloha sa nedá vykonať v Aktuálny stav");
}draft(): ArticleState {
hodiťNovýChyba(„Neplatná operácia: Úloha sa nedá vykonať v Aktuálny stav");
}edit(): ArticleState {
hodiťNovýChyba(„Neplatná operácia: Úloha sa nedá vykonať v Aktuálny stav");
}
publikovať(): ArticleState {
hodiťNovýChyba(„Neplatná operácia: Úloha sa nedá vykonať v Aktuálny stav");
}
}
Vo vyššie uvedenej základnej triede každá metóda spôsobí chybu. Teraz musíte prepísať každú metódu vytvorením špecifických tried predlžuje základná trieda pre každý štát. Každá špecifická trieda bude obsahovať logiku špecifickú pre daný stav.
Každá aplikácia má nečinný stav, ktorý inicializuje aplikáciu. Nečinný stav pre túto aplikáciu nastaví aplikáciu na návrh štát.
Napríklad:
triedaPendingDraftStatepredlžujeČlánok Štát{
pitch(): ArticleState {
vrátiťNový DraftState();
}
}
The ihrisko metóda v triede vyššie inicializuje aplikáciu nastavením aktuálneho stavu na DraftState.
Ďalej prepíšte zvyšné metódy takto:
triedaDraftStatepredlžujeČlánok Štát{
draft(): ArticleState {
vrátiťNový EditingState();
}
}
Tento kód má prednosť pred návrh metóda a vráti inštanciu EditingState.
triedaEditingStatepredlžujeČlánok Štát{
edit(): ArticleState {
vrátiťNový PublishedState();
}
}
Vyššie uvedený blok kódu má prednosť pred upraviť metóda a vráti inštanciu PublishedState.
triedaPublishedStatepredlžujeČlánok Štát{
publikovať(): ArticleState {
vrátiťNový PendingDraftState();
}
}
Vyššie uvedený blok kódu má prednosť pred zverejniť metódu a vráti aplikáciu späť do jej nečinného stavu, PendingDraftState.
Potom musíte aplikácii umožniť interne zmeniť svoj stav odkazovaním na aktuálny stav prostredníctvom súkromnej premennej. Môžete to urobiť inicializáciou nečinného stavu vo vašej triede aplikácie a uložením hodnoty do súkromnej premennej:
súkromné stav: ArticleState = Nový PendingDraftState();
Ďalej aktualizujte showCurrentState metóda na vytlačenie hodnoty aktuálneho stavu:
súkromnéshowCurrentState(): neplatné{
konzoly.log(toto.štát);
}
The showCurrentState metóda zaznamenáva aktuálny stav aplikácie do konzoly.
Nakoniec priraďte súkromnú premennú k aktuálnej inštancii stavu v každej z metód vašej aplikácie.
Napríklad aktualizujte svoje aplikácie ihrisko metóda do bloku kódu nižšie:
verejnostiihrisko(): neplatné{
toto.štát = toto.state.pitch();
toto.showCurrentState();
}
Vo vyššie uvedenom bloku kódu je ihrisko metóda zmení stav z aktuálneho stavu na stav výšky tónu.
Podobne všetky ostatné metódy zmenia stav z aktuálneho stavu aplikácie na príslušné stavy.
Aktualizujte svoje aplikačné metódy na bloky kódu nižšie:
The návrh metóda:
verejnostinávrh(): neplatné{
toto.štát = toto.state.draft();
toto.showCurrentState();
}
The upraviť metóda:
verejnostiupraviť(): neplatné{
toto.štát = toto.state.edit();
toto.showCurrentState();
}
A zverejniť metóda:
verejnostizverejniť(): neplatné{
toto.štát = toto.state.publish();
toto.showCurrentState();
}
Použitie dokončenej aplikácie
Vaša dokončená trieda aplikácií by mala byť podobná bloku kódu nižšie:
// Aplikácia
triedaČlánoknáradiaRozhranie článku{
súkromné stav: ArticleState = Nový PendingDraftState();konštruktér() {
toto.showCurrentState();
}súkromnéshowCurrentState(): neplatné{
konzoly.log(toto.štát);
}verejnostiihrisko(): neplatné{
toto.štát = toto.state.pitch();
toto.showCurrentState();
}verejnostinávrh(): neplatné{
toto.štát = toto.state.draft();
toto.showCurrentState();
}verejnostiupraviť(): neplatné{
toto.štát = toto.state.edit();
toto.showCurrentState();
}
verejnostizverejniť(): neplatné{
toto.štát = toto.state.publish();
toto.showCurrentState();
}
}
Prechody stavov môžete otestovať volaním metód v správnom poradí. Napríklad:
konšt dokumenty = Nový článok(); // PendingDraftState: {}
docs.pitch(); // DraftState: {}
docs.draft(); // Stav úpravy: {}
docs.edit(); // PublishedState: {}
docs.publish(); // PendingDraftState: {}
Vyššie uvedený blok kódu funguje, pretože stavy aplikácie sa primerane zmenili.
Ak sa pokúsite zmeniť stav spôsobom, ktorý nie je povolený, napríklad zo stavu výšky tónu na stav úpravy, aplikácia vyvolá chybu:
konšt dokumenty = Nový článok(); // PendingDraftState: {}
docs.pitch() // DraftState: {}
docs.edit() // Neplatná operácia: Úlohu nemožno vykonať v aktuálnom stave
Tento vzor by ste mali použiť iba vtedy, keď:
- Vytvárate objekt, ktorý sa správa odlišne v závislosti od jeho aktuálneho stavu.
- Objekt má veľa stavov.
- Správanie špecifické pre daný stav sa často mení.
Výhody a nevýhody štátneho vzoru
Tento vzor eliminuje objemné podmienené vyhlásenia a zachováva jednotnú zodpovednosť a princípy otvorené/uzavreté. Ale môže to byť prehnané, ak má aplikácia málo stavov alebo jej stavy nie sú obzvlášť dynamické.