亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JS設(shè)計模式之命令模式的用法詳解

 更新時間:2023年08月27日 10:07:50   作者:慕仲卿  
JavaScript中的命令模式是一種設(shè)計模式,它提供了一種將命令封裝為對象的方式,從而允許我們將請求與實際執(zhí)行該請求的操作對象解耦,這種模式可以在不同的場景中使用,例如實現(xiàn)撤銷/重做操作、隊列任務等,本文我們將講解命令設(shè)計模式在JS中的使用

相關(guān)定義:

  • 使用命令模式,可以將【請求的調(diào)用者】和【請求的執(zhí)行者】解耦。

  • 調(diào)用者通過【持有命令對象】來【間接調(diào)用】接收者的方法,而無需【直接引用】接收者或了解其【具體實現(xiàn)】。

  • 這種解耦使得我們能夠更加靈活地【擴展】和【改變】命令的調(diào)用方式。

  • 例如,我們可以【將命令對象保存在【隊列中】】,實現(xiàn)命令的【排隊】和【異步執(zhí)行】。

  • 還可以記錄命令的【歷史,以支持撤銷和重做】操作。

  • 命令模式應用場景,【菜單操作】、【多級撤銷】、【批處理任務】等。

自我理解:

  • 執(zhí)行者對象E:普通對象,提供了整個流程中的執(zhí)行方法,此方法對于具體的命令是可感知的,對于調(diào)用者是無感知的!

  • 抽象命令類A:規(guī)定了具體命令的基本結(jié)構(gòu),為調(diào)用者提供統(tǒng)一的調(diào)用接口。

  • 具體命令類S:是對抽象命令類的實現(xiàn),核心是封裝了執(zhí)行者,準確來說命令只封裝了執(zhí)行者的部分方法;抽象方法的執(zhí)行本質(zhì)上是執(zhí)行了這些方法。

  • 調(diào)用者對象C:封裝了兩個方法和一個屬性;屬性表示的是當前命令,第一個方法是設(shè)置/切換命令具體值,第二個方法是執(zhí)行此方法。

  • S封裝了E,C只能接觸到S,所以C和E是解耦的

  • A和S的關(guān)系是一對多

解耦體現(xiàn):

  • C無需了解S具體內(nèi)容,只需完成觸發(fā) ;

  • S無需知道E怎么完成任務,只需調(diào)用E暴露出來的方法即可;

  • S和E之間是多對多的關(guān)系,即一個S可以由多個E的部分方法組合完成,一個E也可以被不同的S封裝其上不同的部分方法;

  • C維護的不只是一個S,還可以是一個S隊列,當觸發(fā)到來的時候,S隊列依次執(zhí)行。

代碼舉例1:

// 接收者對象
class Light {
? ? turnOn() {}
? ? turnOff() {}
}
// 命令接口
abstract class Command {
? ? abstract execute():void;
}
// 具體命令:打開燈
class TurnOnCommand extends Command {
? ? constructor(public light: Light) { super() }
? ? execute() { this.light.turnOn() }
}
// 具體命令:關(guān)閉燈
class TurnOffCommand extends Command {
? ? constructor(public light: Light) { super() }
? ? execute() { this.light.turnOff() }
}
// 調(diào)用者對象
class RemoteControl {
? ? command: Command;
? ? setCommand(command: Command) { this.command = command }
? ? pressButton() { this.command.execute() }
}
// 使用示例
// 創(chuàng)建執(zhí)行者
const light = new Light();
// 創(chuàng)建具體命令對象,封裝執(zhí)行者
const turnOnCommand = new TurnOnCommand(light);
const turnOffCommand = new TurnOffCommand(light);
// 創(chuàng)建調(diào)用者對象
const remoteControl = new RemoteControl();
// 設(shè)置具體命令對象然后執(zhí)行
remoteControl.setCommand(turnOnCommand);
remoteControl.pressButton();

代碼舉例2:

使用命令設(shè)計模式可以靈活組合網(wǎng)絡(luò)請求,如下所示:

// 請求接收者
class Reciever {
? async get(path: string) {
? ? const res = await fetch(`https://rec.example.com/${path}`);
? ? const data = await res.json();
? }
}
// 命令接口
class Cmd { exe() {} }
// 具體命令:發(fā)送請求
class RCd extends Cmd {
? constructor(public rec, public url) {
? ? super();
? }
? exe() {
? ? return this.rec.get(this.url);
? }
}
// 調(diào)用者對象
class RM {
? cQueue: Cmd[] = [];
? add(command: Cmd) {
? ? this.cQueue.push(command);
? }
? pReq() {
? ? const promises = this.cQueue.map((command) => command.exe());
? ? return Promise.all(promises);
? }
}
// 使用示例
const rec = new Reciever(); // 創(chuàng)建請求接收者
const rM = new RM(); // 創(chuàng)建請求管理者
// 添加具體請求命令
rM.add(new RCd(rec, 'data1'));
rM.add(new RCd(rec, 'data2'));
rM.add(new RCd(rec, 'data3'));
rM.pReq()
? .then(() => {
? ? console.log('所有請求已完成');
? })
? .catch((error) => {
? ? console.error('請求出錯:', error);
? });

代碼舉例3:

使用命令設(shè)計模式實現(xiàn)撤銷和重做,用到了棧數(shù)據(jù)結(jié)構(gòu),如下所示:

// 命令接口:想要用命令策略實現(xiàn)撤銷、重做就必須先在抽象接口中定義好撤銷的接口
abstract class Cmd {
? abstract exe(): void;
? abstract undo(): void;
}
// 具體命令類 - 加法命令
class AddCmd extends Cmd {
? constructor(public rec: Rec, public value: number) {
? ? super();
? }
? exe() {
? ? this.rec.add(this.value);
? }
? undo() {
? ? this.rec.subtract(this.value);
? }
}
// 接收者類
class Rec {
? result = 0;
? add(value: number) { this.result += value }
? subtract(value: number) { this.result -= value }
}
// 調(diào)用者/發(fā)送者
class Invoker {
? cmds: Cmd[] = [];
? xcmd: Cmd[] = [];
? exe(cmd: Cmd) {
? ? cmd.exe();
? ? this.cmds.push(cmd);
? }
? // 重點
? undo() {
? ? const cmd = this.cmds.pop();
? ? if (!cmd) return;
? ? cmd.undo();
? ? this.xcmd.push(cmd);
? }
? // 重點
? redo() {
? ? const cmd = this.xcmd.pop();
? ? if (cmd) {
? ? ? cmd.exe();
? ? ? this.cmds.push(cmd);
? ? }
? }
}
// 示例用法
const rec = new Rec(); // 創(chuàng)建接收者對象
const ivk = new Invoker(); // 創(chuàng)建調(diào)用者對象
const addCmd = new AddCmd(rec, 5); // 創(chuàng)建加法命令
ivk.exe(addCmd); // 執(zhí)行加法命令,結(jié)果為:5
ivk.undo(); // rec.result = 0
ivk.redo(); // rec.result = 5

命令設(shè)計模式和策略設(shè)計模式的不同:

  • 命令設(shè)計模式的最小操作單元是【命令對象】;而策略設(shè)計模式的最小操作單元是方法,或者算法。

  • 命令設(shè)計模式一次只操作一個命令對象;而策略設(shè)計模式為了完成任務可以組合多個策略。

  • 命令設(shè)計模式一般不會將某個命令單獨保存到內(nèi)部狀態(tài)中;而策略設(shè)計模式必須保存當前的策略。

  • 使用命令設(shè)計模式可以實現(xiàn)撤銷、重做等功能、這反映出各個命令之間是平等關(guān)系;而策略設(shè)計模式的各個策略之間可能是先后順序關(guān)系。

原生使用

下面這些是 JavaScript 中常見的原生部分,它們在某種程度上使用到了命令模式的思想和機制。通過封裝行為成具體的對象并在需要時進行調(diào)用,這些原生功能可以提供更靈活、可擴展的方式來處理相關(guān)的請求或操作。

  • 事件處理:JavaScript 中的事件處理機制可以看作是一種命令模式的應用。當用戶與頁面進行交互時,例如點擊按鈕、鍵盤按鍵或鼠標移動等,事件被觸發(fā)并執(zhí)行相應的處理函數(shù)。這里事件就充當了命令對象,而事件處理函數(shù)則扮演著命令的接收者。

  • XMLHttpRequest 對象:在早期的 Ajax 開發(fā)中,我們常使用 XMLHttpRequest 對象來進行異步請求。開發(fā)者可以將每個請求封裝成一個對象,并通過調(diào)用 send() 方法來發(fā)送請求。這里的 XMLHttpRequest 對象和 send() 方法即可看作是命令模式的實現(xiàn),發(fā)送請求的行為被封裝成具體的命令對象。

  • History API:瀏覽器的 History API 提供了對瀏覽器歷史記錄的控制。通過調(diào)用 pushState() 或 replaceState() 方法,我們可以添加或替換瀏覽器的歷史記錄條目,并關(guān)聯(lián)相應的狀態(tài)數(shù)據(jù)。這里的 pushState() 和 replaceState() 方法可以看作是命令對象,用于執(zhí)行添加或替換歷史記錄的操作。

  • document.execCommand():Document 對象的 execCommand() 方法允許在網(wǎng)頁中執(zhí)行命令式的編輯操作,如粘貼、剪切、加粗、斜體等。開發(fā)者可以調(diào)用 execCommand() 方法并傳遞相應的命令參數(shù)來執(zhí)行這些操作,從而實現(xiàn)富文本編輯功能。

  • setTimeout() 和 setInterval():JavaScript 提供了 setTimeout() 和 setInterval() 函數(shù)來實現(xiàn)定時器功能。開發(fā)者可以使用這兩個函數(shù)將一段代碼封裝成一個函數(shù)對象,并在指定的時間間隔后執(zhí)行相應的代碼,相當于將定時器行為封裝成具體的命令對象。

業(yè)務實踐:

  • 按鈕和用戶交互:當你需要實現(xiàn)一個具有撤銷、重做或記錄操作歷史的按鈕交互功能時,可以使用命令模式。每個按鈕可以表示一個命令對象,按下按鈕時執(zhí)行相應的命令操作。

也就是說但凡見到按鈕,都可以使用命令設(shè)計模式。

  • 異步請求管理:當你需要對異步請求進行批處理、隊列化或延遲執(zhí)行時,命令模式可以很好地組織和管理這些請求。將每個請求封裝成一個命令對象,并使用命令隊列來依次執(zhí)行這些命令。

  • 菜單和快捷鍵:當你需要實現(xiàn)復雜的菜單系統(tǒng)或支持快捷鍵操作時,命令模式可以幫助你處理不同的菜單項或快捷鍵動作。每個菜單項或快捷鍵可以關(guān)聯(lián)一個命令對象,觸發(fā)時執(zhí)行相應的命令操作。

  • 動畫控制:當你需要控制頁面元素的復雜動畫序列或狀態(tài)切換時,命令模式可以提供一種有效的方式。每個動畫或狀態(tài)切換可以封裝成一個命令對象,通過調(diào)用者來觸發(fā)執(zhí)行。

  • 歷史記錄與撤銷:當你需要實現(xiàn)撤銷和重做功能或記錄用戶操作歷史時,命令模式非常有用。每個用戶操作可以表示一個命令對象,并在執(zhí)行時更新狀態(tài)或記錄操作,以便支持撤銷和重做操作。

以上就是JS設(shè)計模式之命令模式的用法詳解的詳細內(nèi)容,更多關(guān)于JS命令模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 微信小程序自定義模態(tài)框

    微信小程序自定義模態(tài)框

    這篇文章主要為大家詳細介紹了微信小程序自定義模態(tài)框,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 獲取陰歷(農(nóng)歷)和當前日期的js代碼

    獲取陰歷(農(nóng)歷)和當前日期的js代碼

    這篇文章主要為大家詳細介紹了獲取陰歷(農(nóng)歷)日期的js代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-02-02
  • javascript中不易分清的slice,splice和split三個函數(shù)

    javascript中不易分清的slice,splice和split三個函數(shù)

    這篇文章主要為大家詳細介紹了javascript中不易分清的slice,splice和split三個函數(shù),感興趣的小伙伴們可以參考一下
    2016-03-03
  • 微信小程序自定義組件實現(xiàn)單選功能

    微信小程序自定義組件實現(xiàn)單選功能

    這篇文章主要為大家詳細介紹了微信小程序自定義組件實現(xiàn)單選功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • js判斷日期時間有效性的方法

    js判斷日期時間有效性的方法

    這篇文章主要介紹了判斷js驗證日期時間有效性的方法,需要的朋友可以參考下
    2015-10-10
  • MutationObserver監(jiān)視對DOM?樹所做更改的功能妙用

    MutationObserver監(jiān)視對DOM?樹所做更改的功能妙用

    這篇文章主要為大家介紹了MutationObserver監(jiān)視對DOM?樹所做更改的功能妙用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • js實現(xiàn)時間日期校驗

    js實現(xiàn)時間日期校驗

    這篇文章主要為大家詳細介紹了js實現(xiàn)時間日期校驗,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • js中的json對象詳細介紹

    js中的json對象詳細介紹

    JSON一種簡單的數(shù)據(jù)格式,比xml更輕巧,在JavaScript中處理JSON數(shù)據(jù)不需要任何特殊的API或工具包,下面為大家詳細介紹下js中的json對象
    2014-10-10
  • JS實現(xiàn)圖片平面旋轉(zhuǎn)的方法

    JS實現(xiàn)圖片平面旋轉(zhuǎn)的方法

    這篇文章主要介紹了JS實現(xiàn)圖片平面旋轉(zhuǎn)的方法,涉及JavaScript操作頁面元素樣式動態(tài)變換的相關(guān)技巧,需要的朋友可以參考下
    2016-03-03
  • JavaScript利用fetch實現(xiàn)異步請求的方法實例

    JavaScript利用fetch實現(xiàn)異步請求的方法實例

    傳遞信息到服務器,從服務器獲取信息,是前端發(fā)展的重中之重,尤其是現(xiàn)在前后端分離的大前提下,前后端的數(shù)據(jù)交互是前端的必修科目了,下面這篇文章主要給大家介紹了關(guān)于JavaScript利用fetch實現(xiàn)異步請求的相關(guān)資料,需要的朋友可以參考借鑒。
    2017-07-07

最新評論