Načrtovalni vzorec je predloga, ki rešuje pogosto ponavljajoče se težave pri načrtovanju programske opreme.

Vzorec stanja je vedenjski vzorec, ki objektu omogoča, da spremeni svoje vedenje, ko se spremeni njegovo notranje stanje.

Tukaj se boste naučili uporabljati vzorec stanja v TypeScriptu.

Kaj je državni vzorec?

Vzorec načrtovanja stanja je tesno povezan s končnim strojem, ki opisuje program, ki obstaja v končno število stanj v danem trenutku in se znotraj posameznega stanja obnaša drugače.

Obstajajo omejena, vnaprej določena pravila – prehodi – ki urejajo druga stanja, v katera lahko preide vsako stanje.

Za kontekst, če je bilo nakupovalno naročilo stranke v spletni trgovini »dostavljeno«, ga ni mogoče »preklicati«, ker je že bilo »dostavljeno«. »Dostavljeno« in »Preklicano« sta končni stanji naročila in naročilo se bo obnašalo drugače glede na svoje stanje.

Državni vzorec ustvari razred za vsako možno stanje, z vedenjem, specifičnim za stanje, ki ga vsebuje vsak razred.

Primer aplikacije, ki temelji na stanju

instagram viewer

Recimo, da ustvarjate aplikacijo, ki sledi stanju članka za založniško podjetje. Članek lahko bodisi čaka na odobritev, osnutek lahko pripravi pisec, uredi urednik ali pa je objavljen. To so končna stanja članka, ki bo objavljen; znotraj vsakega edinstvenega stanja se članek obnaša drugače.

S spodnjim diagramom stanja si lahko vizualizirate različna stanja in prehode aplikacije članka:

Pri izvajanju tega scenarija v kodi bi morali najprej prijaviti vmesnik za članek:

vmesnikArticleInterface{
višina tona(): praznina;
osnutek(): praznina;
Uredi(): praznina;
objavi(): praznina;
}

Ta vmesnik bo imel vsa možna stanja aplikacije.

Nato ustvarite aplikacijo, ki izvaja vse metode vmesnika:

// Aplikacija
razredČlanekpripomočkeArticleInterface{
konstruktor() {
to.showCurrentState();
}

zasebnoshowCurrentState(): praznina{
//...
}

javnostivišina tona(): praznina{
//...
}

javnostiosnutek(): praznina{
//...
}

javnostiUredi(): praznina{
//...
}

javnostiobjaviti(): praznina{
//...
}
}

Zasebno showCurrentState metoda je uporabna metoda. Ta vadnica ga uporablja za prikaz, kaj se zgodi v posamezni državi. Ni obvezen del vzorca stanja.

Upravljanje s prehodi stanj

Nato boste morali obravnavati prehode stanj. Obravnava prehoda stanja v vašem razredu aplikacije bi zahtevala veliko pogojne izjave. To bi povzročilo ponavljajočo se kodo, ki jo je težje brati in vzdrževati. Če želite rešiti to težavo, lahko prenesete logiko prehoda za vsako stanje v svoj razred.

Preden napišete vsak razred stanja, morate ustvariti abstrakten osnovni razred, da zagotovite, da bo katera koli metoda, klicana v neveljavnem stanju, povzročila napako.

Na primer:

povzetekrazredArticleStatepripomočkeArticleInterface{
pitch(): ArticleState {
metatinovoNapaka(»Neveljavna operacija: Naloge ni mogoče izvesti v trenutno stanje");
}

osnutek(): ArticleState {
metatinovoNapaka(»Neveljavna operacija: Naloge ni mogoče izvesti v trenutno stanje");
}

edit(): ArticleState {
metatinovoNapaka(»Neveljavna operacija: Naloge ni mogoče izvesti v trenutno stanje");
}

objavi(): ArticleState {
metatinovoNapaka(»Neveljavna operacija: Naloge ni mogoče izvesti v trenutno stanje");
}
}

V zgornjem osnovnem razredu vsaka metoda povzroči napako. Zdaj morate vsako metodo preglasiti z ustvarjanjem posebnih razredov, ki se razteza osnovni razred za vsako državo. Vsak poseben razred bo vseboval logiko, specifično za stanje.

Vsaka aplikacija ima stanje mirovanja, ki inicializira aplikacijo. Stanje mirovanja za to aplikacijo bo aplikacijo nastavilo na osnutek država.

Na primer:

razredPendingDraftStatese raztezaArticleState{
pitch(): ArticleState {
vrnitevnovo DraftState();
}
}

The višina tona metoda v zgornjem razredu inicializira aplikacijo tako, da nastavi trenutno stanje na DraftState.

Nato preglasite preostale metode takole:

razredDraftStatese raztezaArticleState{
osnutek(): ArticleState {
vrnitevnovo Stanje urejanja();
}
}

Ta koda preglasi osnutek in vrne primerek EditingState.

razredEditingStatese raztezaArticleState{
edit(): ArticleState {
vrnitevnovo PublishedState();
}
}

Zgornji blok kode preglasi Uredi in vrne primerek PublishedState.

razredPublishedStatese raztezaArticleState{
objavi(): ArticleState {
vrnitevnovo PendingDraftState();
}
}

Zgornji blok kode preglasi objaviti in aplikacijo vrne v stanje mirovanja, PendingDraftState.

Nato morate dovoliti aplikaciji, da interno spremeni svoje stanje s sklicevanjem na trenutno stanje prek zasebne spremenljivke. To lahko storite tako, da inicializirate stanje mirovanja znotraj razreda aplikacije in shranite vrednost v zasebno spremenljivko:

zasebno stanje: ArticleState = novo PendingDraftState();

Nato posodobite showCurrentState metoda za tiskanje vrednosti trenutnega stanja:

zasebnoshowCurrentState(): praznina{
konzola.log(to.država);
}

The showCurrentState metoda beleži trenutno stanje aplikacije v konzolo.

Končno znova dodelite zasebno spremenljivko primerku trenutnega stanja v vsaki od metod vaše aplikacije.

Na primer, posodobite svoje aplikacije višina tona metodo na spodnji kodni blok:

javnostivišina tona(): praznina{
to.stanje = to.state.pitch();
to.showCurrentState();
}

V zgornjem bloku kode je višina tona metoda spremeni stanje iz trenutnega stanja v stanje višine.

Podobno bodo vse druge metode spremenile stanje iz trenutnega stanja aplikacije v svoja ustrezna stanja.

Posodobite svoje metode uporabe na spodnje bloke kode:

The osnutek metoda:

javnostiosnutek(): praznina{
to.stanje = to.state.draft();
to.showCurrentState();
}

The Uredi metoda:

javnostiUredi(): praznina{
to.stanje = to.state.edit();
to.showCurrentState();
}

In objaviti metoda:

javnostiobjaviti(): praznina{
to.stanje = to.state.publish();
to.showCurrentState();
}

Uporaba končane aplikacije

Vaš končni razred aplikacije bi moral biti podoben spodnjemu bloku kode:

// Aplikacija
razredČlanekpripomočkeArticleInterface{
zasebno stanje: ArticleState = novo PendingDraftState();

konstruktor() {
to.showCurrentState();
}

zasebnoshowCurrentState(): praznina{
konzola.log(to.država);
}

javnostivišina tona(): praznina{
to.stanje = to.state.pitch();
to.showCurrentState();
}

javnostiosnutek(): praznina{
to.stanje = to.state.draft();
to.showCurrentState();
}

javnostiUredi(): praznina{
to.stanje = to.state.edit();
to.showCurrentState();
}

javnostiobjaviti(): praznina{
to.stanje = to.state.publish();
to.showCurrentState();
}
}

Prehode stanj lahko preizkusite tako, da pokličete metode v pravilnem zaporedju. Na primer:

konst dokumenti = novo Članek(); // PendingDraftState: {}

docs.pitch(); // DraftState: {}
docs.draft(); // EditingState: {}
docs.edit(); // PublishedState: {}
docs.publish(); // PendingDraftState: {}

Zgornji blok kode deluje, ker so se stanja aplikacije ustrezno spremenila.

Če poskušate spremeniti stanje na način, ki ni dovoljen, na primer iz stanja višine v stanje urejanja, bo aplikacija vrgla napako:

konst dokumenti = novo Članek(); // PendingDraftState: {}
docs.pitch() // DraftState: {}
docs.edit() // Neveljavna operacija: Naloge v trenutnem stanju ni mogoče izvesti

Ta vzorec uporabite le, kadar:

  • Ustvarjate objekt, ki se glede na trenutno stanje obnaša drugače.
  • Objekt ima veliko stanj.
  • Vedenje, specifično za stanje, se pogosto spreminja.

Prednosti in kompromisi vzorca stanja

Ta vzorec odpravlja obsežne pogojne stavke in ohranja načela ene odgovornosti in odprtega/zaprtega. Vendar je lahko pretirano, če ima aplikacija malo stanj ali njena stanja niso posebej dinamična.