欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS設(shè)計(jì)模式之狀態(tài)模式的用法使用方法

 更新時(shí)間:2023年08月27日 10:00:01   作者:慕仲卿  
JavaScript狀態(tài)模式是一種行為型設(shè)計(jì)模式,核心是對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變其行為,狀態(tài)模式將對(duì)象的行為封裝到不同的狀態(tài)類(lèi)中,使得對(duì)象在不同狀態(tài)下可以選擇不同的行為,本文給大家詳細(xì)的介紹一下?tīng)顟B(tài)設(shè)計(jì)模式在Js中的使用,需要的朋友可以參考下

狀態(tài)模式(State Pattern)

一種行為型設(shè)計(jì)模式,核心是對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變其行為

狀態(tài)模式將對(duì)象的行為封裝到不同的狀態(tài)類(lèi)中,使得對(duì)象在不同狀態(tài)下可以選擇不同的行為。

組成

  • 環(huán)境類(lèi):環(huán)境類(lèi)是擁有狀態(tài)的對(duì)象,它在運(yùn)行時(shí)將自身的操作委托給當(dāng)前的狀態(tài)對(duì)象來(lái)處理。①環(huán)境類(lèi)維護(hù)一個(gè)對(duì)抽象狀態(tài)類(lèi)的引用,②并通過(guò)該引用來(lái)調(diào)用具體狀態(tài)類(lèi)的方法。

  • 抽象狀態(tài)類(lèi):抽象狀態(tài)類(lèi)定義了一個(gè)接口③,用于封裝與環(huán)境類(lèi)的特定狀態(tài)相關(guān)的行為。

  • 具體狀態(tài)類(lèi):具體狀態(tài)類(lèi)實(shí)現(xiàn)了抽象狀態(tài)類(lèi)定義的接口,它具體描述了在某個(gè)狀態(tài)下對(duì)象的行為④。

工作流程

  • 環(huán)境類(lèi)通過(guò)持有一個(gè)抽象狀態(tài)類(lèi)的引用來(lái)表示當(dāng)前的狀態(tài)。

  • 客戶(hù)端通過(guò)調(diào)用環(huán)境類(lèi)的方法來(lái)觸發(fā)某個(gè)操作。

  • 環(huán)境類(lèi)在運(yùn)行時(shí)將操作委托給當(dāng)前狀態(tài)對(duì)象進(jìn)行處理。

  • 當(dāng)對(duì)象的狀態(tài)發(fā)生改變時(shí),環(huán)境類(lèi)會(huì)更新當(dāng)前狀態(tài)對(duì)象的引用,從而改變對(duì)象的行為。

趣例

下面的這個(gè)例子展示了一位西安老鐵觀看國(guó)足比賽的時(shí)候的心理狀態(tài)變化過(guò)程:

abstract class State {
? constructor(public context: Context | null = null) {}
? // 這里體現(xiàn)出③:用于封裝與環(huán)境類(lèi)的特定狀態(tài)相關(guān)的行為
? handle() {
? ? if (!this.context) {
? ? ? console.log("找不到老鐵了!");
? ? } else {
? ? ? this.exec();
? ? }
? }
? next<T extends State>(NextState: new (context: Context) => T) {
? ? if (!this.context) {
? ? ? console.log("找不到老鐵了!");
? ? } else {
? ? ? this.context.to(new NextState(this.context));
? ? }
? }
? abstract exec(): any;
}
// 具體狀態(tài)類(lèi)
class StateA extends State {
? // 這里體現(xiàn)出④:用于封裝與環(huán)境類(lèi)的特定狀態(tài)相關(guān)的行為
? exec() {
? ? console.log("買(mǎi)票");
? ? this.next(StateB);
? }
}
class StateB extends State {
? exec() {
? ? console.log("坐車(chē)");
? ? this.next(StateC);
? }
}
class StateC extends State {
? exec() {
? ? console.log("看球");
? ? this.next(StateO);
? }
}
class StateO extends State {
? exec() {
? ? throw new Error('已經(jīng)結(jié)束了');
? }
}
// 環(huán)境類(lèi)
class Context {
? // 這里體現(xiàn)出①:環(huán)境類(lèi)維護(hù)一個(gè)對(duì)抽象狀態(tài)類(lèi)的引用,即cts
? constructor(public cts: State | null = null) {}
? to(state: State) {
? ? console.log(`Transitioning to ${state.constructor.name}`);
? ? this.cts = state;
? }
? do() {
? ? // 這里體現(xiàn)出②:通過(guò)該引用來(lái)調(diào)用具體狀態(tài)類(lèi)的方法
? ? this.cts?.handle();
? }
}
// 使用示例
const context = new Context();
const stateA = new StateA(context);
context.to(stateA);
while(1){
? try {
? ? context.do();
? } catch {
? ? console.log('肯定輸了!');
? ? break;
? }
}

對(duì)照例子理解

  • 狀態(tài)模式:一種行為型設(shè)計(jì)模式,核心是①【對(duì)象】在其②【內(nèi)部狀態(tài)】③【改變】時(shí)④【改變其行為】。
  • ①對(duì)象:指的是環(huán)境類(lèi)對(duì)象,也就是上述代碼中的context對(duì)象。

  • ②內(nèi)部狀態(tài),指的是context引用的狀態(tài)類(lèi)實(shí)例,也就是stateA以及NextState的匿名實(shí)例。

  • ③改變:指的是context.to的調(diào)用。

  • ④行為:指的是context.do函數(shù)的執(zhí)行結(jié)果。

  • 改變其行為:指的是context.cts引用不同的狀態(tài)類(lèi)實(shí)例的時(shí)候context.do的執(zhí)行結(jié)果不同。

  • 狀態(tài)模式將對(duì)象的行為封裝到不同的狀態(tài)類(lèi)中,使得對(duì)象在不同狀態(tài)下可以選擇不同的行為。

    這句話理解成:

    • 本來(lái)應(yīng)該在context.do中通過(guò)if else實(shí)現(xiàn)的功能,被封裝到了不同的狀態(tài)類(lèi)中(StateA StateB);

    • 當(dāng)context的狀態(tài)改變的時(shí)候(即:context.cts引用不同的狀態(tài)類(lèi)實(shí)例的時(shí)候)context.do也能實(shí)現(xiàn)封裝前相同的功能(即表現(xiàn)出不同的行為)。

見(jiàn)下面代碼:

不使用狀態(tài)設(shè)計(jì)模式實(shí)現(xiàn)上述代碼功能:

class Context {
? state = 'A';
? to(state: string) {
? ? console.log(`Transitioning to state ${state}`);
? ? this.state = state;
? }
? do() {
? ? if(this.state === 'A'){
? ? ? console.log("買(mǎi)票");
? ? ? this.to('B');
? ? } else if (this.state === 'B') {
? ? ? console.log("坐車(chē)");
? ? ? this.to('C');
? ? } else if (this.state === 'C') {
? ? ? console.log("看球");
? ? ? this.to('D');
? ? } else if (this.state === 'D') {
? ? ? throw new Error('已經(jīng)結(jié)束了');
? ? }
? }
}
const context = new Context();
while(1){
? try {
? ? context.do();
? } catch {
? ? console.log('肯定輸了!');
? ? break;
? }
}

【對(duì)比】雖然這樣看起來(lái)代碼量好像少了一些,但是如果老鐵想要在下車(chē)后去趟衛(wèi)生間,使用了狀態(tài)設(shè)計(jì)模式的代碼只需要修改StateB的實(shí)現(xiàn)就可以了,而后者則必須修改Context中的do方法!

優(yōu)點(diǎn)

  • 封裝之后的狀態(tài)可以獨(dú)立變化,符合開(kāi)閉原則。

  • 狀態(tài)模式提供了一種清晰的方式來(lái)組織對(duì)象的行為,并避免了使用大量的條件語(yǔ)句。

缺點(diǎn)

  • 狀態(tài)較多時(shí),導(dǎo)致?tīng)顟B(tài)類(lèi)的數(shù)量增加,增加系統(tǒng)的復(fù)雜性。

  • 對(duì)象在不同狀態(tài)下的轉(zhuǎn)換邏輯可能會(huì)分散在多個(gè)狀態(tài)類(lèi)中,使得代碼難以理解和維護(hù)。

  • 如果某個(gè)狀態(tài)只被一個(gè)對(duì)象使用,可以考慮使用策略模式替代狀態(tài)模式。

應(yīng)用

狀態(tài)模式常見(jiàn)于需要根據(jù)對(duì)象的內(nèi)部狀態(tài)來(lái)改變其行為的場(chǎng)景,例如【訂單狀態(tài)的處理】、【游戲角色的狀態(tài)轉(zhuǎn)換】等。

它提供了一種可擴(kuò)展的方式來(lái)處理狀態(tài)相關(guān)的邏輯,并促進(jìn)了代碼的靈活性和可維護(hù)性。

generator函數(shù)可以看成原生js實(shí)現(xiàn)了狀態(tài)設(shè)計(jì)模式。

感性記憶

同一個(gè)對(duì)象,當(dāng)其內(nèi)部維護(hù)的狀態(tài)不同的時(shí)候,調(diào)用其上的同一個(gè)方法,可能會(huì)得到完全不同的結(jié)果。

總結(jié)

就是適用于同一個(gè)對(duì)象具有不同的狀態(tài),并且在各個(gè)狀態(tài)下表現(xiàn)不一致的情況;這些狀態(tài)之間如果是可以相互轉(zhuǎn)換的,使用此設(shè)計(jì)模式就更加合適了。

到此這篇關(guān)于JS設(shè)計(jì)模式之狀態(tài)模式的用法使用方法的文章就介紹到這了,更多相關(guān)JS狀態(tài)模式使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論