Een ontwerppatroon is een sjabloon dat een veelvoorkomend probleem bij het ontwerpen van software oplost.

Het toestandspatroon is een gedragspatroon dat een object zijn gedrag laat veranderen wanneer zijn interne toestand verandert.

Hier leert u hoe u het statuspatroon in TypeScript gebruikt.

Wat is het toestandspatroon?

Het toestandsontwerppatroon is nauw verwant aan een eindige-toestandsmachine, die een programma beschrijft dat bestaat in a eindig aantal toestanden op een bepaald moment en gedraagt ​​zich binnen elke toestand anders.

Er zijn beperkte, vooraf bepaalde regels - overgangen - die gelden voor de andere staten waarnaar elke staat kan overschakelen.

Voor de context, in een online winkel, als de winkelbestelling van een klant is 'bezorgd', kan deze niet worden 'geannuleerd' omdat deze al is 'bezorgd'. "Bezorgd" en "Geannuleerd" zijn eindige statussen van de bestelling en de bestelling zal zich anders gedragen op basis van de status.

Het staatspatroon creëert een klas voor elke mogelijke status, met statusspecifiek gedrag in elke klasse.

instagram viewer

Een voorbeeld van een op de staat gebaseerde toepassing

Stel bijvoorbeeld dat u een toepassing maakt die de status van een artikel bijhoudt voor een uitgeverij. Een artikel kan in afwachting van goedkeuring zijn, opgesteld door een schrijver, bewerkt door een redacteur of gepubliceerd. Dit zijn de eindige toestanden van een te publiceren artikel; binnen elke unieke status gedraagt ​​het artikel zich anders.

U kunt de verschillende toestanden en overgangen van de artikeltoepassing visualiseren met het onderstaande toestandsdiagram:

Als u dit scenario in code implementeert, moet u eerst een interface voor het artikel declareren:

koppelArtikelInterface{
toonhoogte(): leegte;
voorlopige versie(): leegte;
bewerking(): leegte;
publiceren(): leegte;
}

Deze interface heeft alle mogelijke statussen van de applicatie.

Maak vervolgens een applicatie die alle interfacemethoden implementeert:

// Sollicitatie
klasArtikelimplementeertArtikelInterface{
constructeur() {
dit.showCurrentState();
}

privaatshowCurrentState(): leegte{
//...
}

openbaartoonhoogte(): leegte{
//...
}

openbaarvoorlopige versie(): leegte{
//...
}

openbaarbewerking(): leegte{
//...
}

openbaarpubliceren(): leegte{
//...
}
}

De privé showCurrentState methode is een gebruiksmethode. Deze tutorial gebruikt het om te laten zien wat er in elke staat gebeurt. Het is geen verplicht onderdeel van het statuspatroon.

Omgaan met staatsovergangen

Vervolgens moet u de statusovergangen afhandelen. Om de toestandsovergang in uw toepassingsklasse af te handelen, zijn er veel nodig Voorwaardelijke stellingen. Dit zou resulteren in repetitieve code die moeilijker te lezen en te onderhouden is. Om dit probleem op te lossen, kunt u de overgangslogica voor elke status naar zijn eigen klasse delegeren.

Voordat u elke statusklasse schrijft, moet u een abstracte basisklasse maken om ervoor te zorgen dat elke methode die wordt aangeroepen in een ongeldige status een fout genereert.

Bijvoorbeeld:

abstractklasArtikelStaatimplementeertArtikelInterface{
toonhoogte(): ArticleState {
gooiennieuwFout("Ongeldige bewerking: kan taak niet uitvoeren in huidige toestand");
}

concept(): ArticleState {
gooiennieuwFout("Ongeldige bewerking: kan taak niet uitvoeren in huidige toestand");
}

edit(): ArticleState {
gooiennieuwFout("Ongeldige bewerking: kan taak niet uitvoeren in huidige toestand");
}

publiceren(): ArticleState {
gooiennieuwFout("Ongeldige bewerking: kan taak niet uitvoeren in huidige toestand");
}
}

In de bovenstaande basisklasse genereert elke methode een fout. Nu moet je elke methode overschrijven door specifieke klassen te maken die strekt zich uit de basisklasse voor elke staat. Elke specifieke klasse bevat toestandspecifieke logica.

Elke toepassing heeft een inactieve status, die de toepassing initialiseert. De inactieve status voor deze toepassing stelt de toepassing in op de voorlopige versie staat.

Bijvoorbeeld:

klasIn afwachting van DraftStatestrekt zich uitArtikelStaat{
toonhoogte(): ArticleState {
opbrengstnieuw DraftState();
}
}

De toonhoogte methode in de bovenstaande klasse initialiseert de toepassing door de huidige status in te stellen op ontwerpstaat.

Overschrijf vervolgens de rest van de methoden als volgt:

klasontwerpstaatstrekt zich uitArtikelStaat{
concept(): ArticleState {
opbrengstnieuw Staat bewerken();
}
}

Deze code overschrijft de voorlopige versie methode en retourneert een instantie van de Staat bewerken.

klasStaat bewerkenstrekt zich uitArtikelStaat{
edit(): ArticleState {
opbrengstnieuw GepubliceerdStatus();
}
}

Het codeblok hierboven overschrijft de bewerking methode en retourneert een instantie van Gepubliceerde staat.

klasGepubliceerde staatstrekt zich uitArtikelStaat{
publiceren(): ArticleState {
opbrengstnieuw PendingDraftState();
}
}

Het codeblok hierboven overschrijft de publiceren methode en zet de applicatie terug in de ruststand, In afwachting van DraftState.

Vervolgens moet u de toepassing toestemming geven om de status intern te wijzigen door naar de huidige status te verwijzen via een privévariabele. U kunt dit doen door de inactieve status binnen uw toepassingsklasse te initialiseren en de waarde op te slaan in een privévariabele:

privaat staat: ArticleState = nieuw PendingDraftState();

Werk vervolgens de showCurrentState methode om de huidige statuswaarde af te drukken:

privaatshowCurrentState(): leegte{
troosten.log(dit.staat);
}

De showCurrentState methode registreert de huidige status van de applicatie naar de console.

Wijs ten slotte de privévariabele opnieuw toe aan de huidige statusinstantie in elk van de methoden van uw toepassing.

Werk bijvoorbeeld uw applicaties bij toonhoogte methode naar het onderstaande codeblok:

openbaartoonhoogte(): leegte{
dit.staat = dit.state.pitch();
dit.showCurrentState();
}

In het codeblok hierboven, de toonhoogte methode verandert de status van de huidige status naar de toonhoogtestatus.

Evenzo zullen alle andere methoden de status van de huidige toepassingsstatus wijzigen in hun respectievelijke statussen.

Werk uw toepassingsmethoden bij naar de onderstaande codeblokken:

De voorlopige versie methode:

openbaarvoorlopige versie(): leegte{
dit.staat = dit.state.ontwerp();
dit.showCurrentState();
}

De bewerking methode:

openbaarbewerking(): leegte{
dit.staat = dit.staat.bewerken();
dit.showCurrentState();
}

En de publiceren methode:

openbaarpubliceren(): leegte{
dit.staat = dit.staat.publiceren();
dit.showCurrentState();
}

De voltooide toepassing gebruiken

Uw voltooide toepassingsklasse moet vergelijkbaar zijn met het onderstaande codeblok:

// Sollicitatie
klasArtikelimplementeertArtikelInterface{
privaat staat: ArticleState = nieuw PendingDraftState();

constructeur() {
dit.showCurrentState();
}

privaatshowCurrentState(): leegte{
troosten.log(dit.staat);
}

openbaartoonhoogte(): leegte{
dit.staat = dit.state.pitch();
dit.showCurrentState();
}

openbaarvoorlopige versie(): leegte{
dit.staat = dit.state.ontwerp();
dit.showCurrentState();
}

openbaarbewerking(): leegte{
dit.staat = dit.staat.bewerken();
dit.showCurrentState();
}

openbaarpubliceren(): leegte{
dit.staat = dit.staat.publiceren();
dit.showCurrentState();
}
}

U kunt de toestandsovergangen testen door de methoden in de juiste volgorde aan te roepen. Bijvoorbeeld:

const documenten = nieuw Artikel(); // PendingDraftState: {}

docs.pitch(); // DraftState: {}
docs.concept(); // Bewerkingsstatus: {}
docs.bewerken(); // Gepubliceerde staat: {}
docs.publiceren(); // PendingDraftState: {}

Het bovenstaande codeblok werkt omdat de toestanden van de toepassing op de juiste manier zijn overgegaan.

Als u de status probeert te wijzigen op een manier die niet is toegestaan, bijvoorbeeld van de toonhoogtestatus naar de bewerkingsstatus, genereert de toepassing een fout:

const documenten = nieuw Artikel(); // PendingDraftState: {}
docs.pitch() // DraftState: {}
docs.bewerken() // Ongeldige bewerking: kan de taak in de huidige status niet uitvoeren

Gebruik dit patroon alleen wanneer:

  • U maakt een object dat zich anders gedraagt, afhankelijk van de huidige status.
  • Het object heeft vele toestanden.
  • Het staatsspecifieke gedrag verandert regelmatig.

Voordelen en afwegingen van het toestandspatroon

Dit patroon elimineert omvangrijke voorwaardelijke verklaringen en handhaaft de enkele verantwoordelijkheid en open/gesloten principes. Maar het kan overdreven zijn als de applicatie weinig statussen heeft of als de statussen niet bijzonder dynamisch zijn.