Návrhový vzor je šablona, která řeší běžně se opakující problém v návrhu softwaru.
Vzorec stavu je vzorec chování, který umožňuje objektu změnit své chování, když se změní jeho vnitřní stav.
Zde se dozvíte, jak používat vzor stavu v TypeScriptu.
Jaký je státní vzor?
Stavový návrhový vzor úzce souvisí s konečným automatem, který popisuje program, který existuje v a konečný počet stavů v daném okamžiku a v každém státě se chová jinak.
Existují omezená, předem určená pravidla – přechody –, která řídí ostatní stavy, do kterých může každý stát přejít.
Pro kontext, v internetovém obchodě, pokud byla nákupní objednávka zákazníka „doručena“, nelze ji „zrušit“, protože již byla „doručena“. „Doručeno“ a „Zrušeno“ jsou konečné stavy objednávky a objednávka se bude chovat odlišně podle svého stavu.
Vzor státu vytvoří třídu pro každý možný stav, se stavově specifickým chováním obsaženým v každé třídě.
Příklad státní aplikace
Předpokládejme například, že vytváříte aplikaci, která sleduje stavy článku pro vydavatelskou společnost. Článek může buď čekat na schválení, může být navržen spisovatelem, upravován editorem nebo publikován. Toto jsou konečné stavy článku, který má být publikován; v rámci každého jedinečného stavu se článek chová jinak.
Pomocí stavového diagramu níže si můžete vizualizovat různé stavy a přechody aplikace článku:
Při implementaci tohoto scénáře v kódu byste nejprve museli deklarovat rozhraní pro článek:
rozhraníRozhraní článku{
výška(): prázdnota;
návrh(): prázdnota;
Upravit(): prázdnota;
publikovat(): prázdnota;
}
Toto rozhraní bude mít všechny možné stavy aplikace.
Dále vytvořte aplikaci, která implementuje všechny metody rozhraní:
// Aplikace
třídaČláneknářadíRozhraní článku{
konstruktér() {
tento.showCurrentState();
}soukroméshowCurrentState(): prázdnota{
//...
}veřejnosthřiště(): prázdnota{
//...
}veřejnostnávrh(): prázdnota{
//...
}veřejnostUpravit(): prázdnota{
//...
}
veřejnostpublikovat(): prázdnota{
//...
}
}
Soukromý showCurrentState metoda je užitková metoda. Tento tutoriál jej používá k tomu, aby ukázal, co se děje v každém stavu. Není to povinná součást státního vzoru.
Zpracování přechodů stavů
Dále budete muset zvládnout přechody stavů. Zpracování přechodu stavu ve vaší aplikační třídě by vyžadovalo mnoho podmíněné příkazy. To by mělo za následek opakující se kód, který je obtížnější číst a udržovat. Chcete-li tento problém vyřešit, můžete delegovat logiku přechodu pro každý stav na jeho vlastní třídu.
Než napíšete každou třídu stavu, měli byste vytvořit abstraktní základní třídu, abyste zajistili, že jakákoli metoda volaná v neplatném stavu vyvolá chybu.
Například:
abstraktnítřídaArticleStatenářadíRozhraní článku{
pitch(): ArticleState {
házetNovýChyba("Neplatná operace: Nelze provést úlohu v aktuální stav");
}draft(): ArticleState {
házetNovýChyba("Neplatná operace: Nelze provést úlohu v aktuální stav");
}edit(): ArticleState {
házetNovýChyba("Neplatná operace: Nelze provést úlohu v aktuální stav");
}
publikovat(): ArticleState {
házetNovýChyba("Neplatná operace: Nelze provést úlohu v aktuální stav");
}
}
Ve výše uvedené základní třídě každá metoda vyvolá chybu. Nyní musíte každou metodu přepsat vytvořením konkrétních tříd rozšiřuje základní třída pro každý stát. Každá konkrétní třída bude obsahovat logiku specifickou pro stav.
Každá aplikace má klidový stav, který inicializuje aplikaci. Nečinný stav této aplikace nastaví aplikaci na návrh Stát.
Například:
třídaPendingDraftStaterozšiřujeArticleState{
pitch(): ArticleState {
vrátit seNový DraftState();
}
}
The hřiště metoda ve třídě výše inicializuje aplikaci nastavením aktuálního stavu na DraftState.
Dále přepište zbývající metody takto:
třídaDraftStaterozšiřujeArticleState{
draft(): ArticleState {
vrátit seNový EditingState();
}
}
Tento kód má přednost před návrh metoda a vrátí instanci EditingState.
třídaEditingStaterozšiřujeArticleState{
edit(): ArticleState {
vrátit seNový PublishedState();
}
}
Blok kódu výše přepíše Upravit metoda a vrátí instanci PublishedState.
třídaPublishedStaterozšiřujeArticleState{
publikovat(): ArticleState {
vrátit seNový PendingDraftState();
}
}
Blok kódu výše přepíše publikovat metodu a vrátí aplikaci zpět do klidového stavu, PendingDraftState.
Poté musíte aplikaci povolit, aby interně změnila svůj stav odkazem na aktuální stav prostřednictvím soukromé proměnné. Můžete to provést inicializací nečinného stavu uvnitř třídy aplikace a uložením hodnoty do soukromé proměnné:
soukromé stav: ArticleState = Nový PendingDraftState();
Dále aktualizujte showCurrentState způsob tisku aktuální hodnoty stavu:
soukroméshowCurrentState(): prázdnota{
řídicí panel.log(tento.Stát);
}
The showCurrentState metoda zaznamenává aktuální stav aplikace do konzole.
Nakonec znovu přiřaďte privátní proměnnou k aktuální instanci stavu v každé z metod vaší aplikace.
Aktualizujte například své aplikace hřiště metoda do bloku kódu níže:
veřejnosthřiště(): prázdnota{
tento.stát = tento.state.pitch();
tento.showCurrentState();
}
Ve výše uvedeném bloku kódu je hřiště metoda změní stav z aktuálního stavu na stav pitch.
Podobně všechny ostatní metody změní stav z aktuálního stavu aplikace na příslušné stavy.
Aktualizujte své aplikační metody na bloky kódu níže:
The návrh metoda:
veřejnostnávrh(): prázdnota{
tento.stát = tento.state.draft();
tento.showCurrentState();
}
The Upravit metoda:
veřejnostUpravit(): prázdnota{
tento.stát = tento.state.edit();
tento.showCurrentState();
}
A publikovat metoda:
veřejnostpublikovat(): prázdnota{
tento.stát = tento.state.publish();
tento.showCurrentState();
}
Pomocí hotové aplikace
Vaše dokončená třída aplikace by měla být podobná bloku kódu níže:
// Aplikace
třídaČláneknářadíRozhraní článku{
soukromé stav: ArticleState = Nový PendingDraftState();konstruktér() {
tento.showCurrentState();
}soukroméshowCurrentState(): prázdnota{
řídicí panel.log(tento.Stát);
}veřejnosthřiště(): prázdnota{
tento.stát = tento.state.pitch();
tento.showCurrentState();
}veřejnostnávrh(): prázdnota{
tento.stát = tento.state.draft();
tento.showCurrentState();
}veřejnostUpravit(): prázdnota{
tento.stát = tento.state.edit();
tento.showCurrentState();
}
veřejnostpublikovat(): prázdnota{
tento.stát = tento.state.publish();
tento.showCurrentState();
}
}
Přechody stavů můžete otestovat voláním metod ve správném pořadí. Například:
konst dokumenty = Nový Článek(); // PendingDraftState: {}
docs.pitch(); // DraftState: {}
docs.draft(); // EditingState: {}
docs.edit(); // PublishedState: {}
docs.publish(); // PendingDraftState: {}
Výše uvedený blok kódu funguje, protože stavy aplikace se vhodně převedly.
Pokud se pokusíte změnit stav způsobem, který není povolen, například ze stavu pitch na stav úprav, aplikace vyvolá chybu:
konst dokumenty = Nový Článek(); // PendingDraftState: {}
docs.pitch() // DraftState: {}
docs.edit() // Neplatná operace: V aktuálním stavu nelze provést úlohu
Tento vzor byste měli používat pouze tehdy, když:
- Vytváříte objekt, který se chová odlišně v závislosti na jeho aktuálním stavu.
- Objekt má mnoho stavů.
- Chování specifické pro stav se často mění.
Výhody a nevýhody státního vzoru
Tento vzor eliminuje objemná podmíněná prohlášení a zachovává jednotnou odpovědnost a zásady otevřené/uzavřené. Ale může to být přehnané, pokud má aplikace málo stavů nebo její stavy nejsou nijak zvlášť dynamické.