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

javascript設(shè)計模式之命令模式

 更新時間:2022年01月15日 16:58:58   作者:石頭山_S  
這篇文章主要為大家介紹了javascript命令模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

一. 認(rèn)識命令模式

所謂命令,也就是指執(zhí)行某些特定事情的指令,就拿喝水的例子來說,喝水執(zhí)行的指令就是將水倒在杯子里,然后端起杯子送入口中,這就是一條命令,無論誰喝水都是這個步驟,我們不關(guān)心是誰端起了杯子,也不關(guān)心杯子中的水到底是水還是其他東西。我們只關(guān)心這個過程,將水倒在杯子中,然后端起杯子送入口中,最后誰喝掉了,喝掉的是飲料還是水不重要。

大家可能聽的有點混,而命令模式最常見的應(yīng)用場景就是:有時候需要向某些對象發(fā)送請求,但是并不知道請求的接收者是誰,也不知道被請求的操作是什么。此時我們用一種松耦合的方式來設(shè)計程序,使得請求發(fā)送者和接收者能夠消除彼此間的耦合關(guān)系。

二. 代碼實現(xiàn)-實際應(yīng)用場景

在實際開發(fā)中團(tuán)隊協(xié)作是最重要的環(huán)節(jié),假如兩個人分別得到兩個不同的任務(wù),一個人負(fù)責(zé)頁面中所有的 button 按鈕的美化,另一個人負(fù)責(zé)實現(xiàn)這些 button 的邏輯,我們在寫 button 邏輯時不知道該 button 最終綁定的是頁面中的哪一個按鈕,也不知道具體點擊該按鈕會發(fā)生什么,此時我們用命令模式來設(shè)計,來解開按鈕和負(fù)責(zé)具體行為對象間的耦合,代碼如下所示。

    <script>
        let btns = document.querySelectorAll('button');
        // 寫一個刷新命令
        let refreshCommand = {
            execute () {
                console.log("刷新頁面");
            }
        }
        // 寫一個登錄按鈕命令
        let loginCommand = {
            execute () {
                console.log("執(zhí)行登錄操作");
            }
        }
        let setCommand = function( button, command) {
            button.onclick = function() {
                command.execute();
            }
        }
        // 假如第三個按鈕用來負(fù)責(zé)刷新頁面,第五個用來負(fù)責(zé)登錄操作
        setCommand( btns[2], refreshCommand);
        setCommand( btns[4], loginCommand);  

分析:我們將點擊按鈕后可能會發(fā)生的事件分別封裝起來,它們中各自有自己的 execute 函數(shù),我們將安裝按鈕功能的函數(shù)封裝到了 setCommand 中,最后根據(jù)需求對應(yīng)安裝各個按鈕的功能便可。

三. 命令模式的撤銷操作

下達(dá)一個命令后,我們可能不需要了,想回到下達(dá)命令之前的狀態(tài),就需要用到撤銷操作,撤銷操作的實現(xiàn)一般是給命令對象增加一個 undo 或者 unexecute 方法,在其中執(zhí)行 execute 的反向操作。

// 假如寫一個人物向左移的命令
let moveLeftCommand = {
    execute() {
        console.log("人物向左移動");
}
    undo (){
        console.log("人物向又移動");
}
}

這種是簡單的邏輯實現(xiàn),假如有些撤銷行為無法用執(zhí)行他的反向操作來實現(xiàn),那我們應(yīng)該怎么辦呢?

帶著這個問題我們學(xué)習(xí)一種新的達(dá)到撤銷的方式,我們用一個棧來記錄每一步命令,想要撤銷,我們只需要重頭開始,從棧中拿出命令來分別執(zhí)行,將最后一次命令刪除即可。如果不刪除最后一次命令依次執(zhí)行,我們又實現(xiàn)了一個新的功能,重播。

這是一個通過 WASD 來控制小球移動的代碼實現(xiàn),我們每次按下一個有效命令時,便會將該命令推入 commandStack 中來記錄小球的變化,當(dāng)點擊重播時小球會按照之前同樣的軌跡運(yùn)動。

        let role = document.getElementById('role');
        
        let move = {
            dom: role,
            leftt:0,
            top: 0,
            up() {
                console.log("向上");
                this.top -= 10;
                this.dom.style.top = this.top + 'px';
            },
            down(){
                console.log("向下");
                this.top += 10;
                this.dom.style.top = this.top + 'px';
            },
            left() {
                console.log("向左");
                this.leftt -= 10;
                this.dom.style.left = this.leftt + 'px';
            },
            right() {
                console.log("向右");
                this.leftt += 10;
                this.dom.style.left = this.leftt + 'px';
            }
        }
        commands = {
            "119": "up",      // W
            "115": "down",    // S
            "97": "left",    // A
            "100": "right"     // D
        };
        commandStack = []; // 保存命令的堆棧
        let setCommand = function (receiver, state) {
            return function() {
                receiver[state]();
            }
        }
        document.addEventListener('keypress', (e) => {
            let code = e.charCode;
            if(!commands[code]) {
                return ;
            }
            let command = setCommand(move, commands[code]);
            if( command ) {
                command();
                commandStack.push( command );
            }
        })
        // 設(shè)置重播按鈕
        document.getElementById('replay').onclick = function() {
            let command;
            while(command = commandStack.shift()) {
                command();
            }
        }

四. 宏命令

宏命令就是一組命令的集合,通過執(zhí)行宏命令可以一次執(zhí)行一批命令。

通俗來說就是,有一件事你需要重復(fù)做,并且做這件事的每一步都是固定不變的,那么我們可以將做這件事情的所有步驟打包起來,只需要啟動,便可以自動完成所有步驟。

需求:實現(xiàn)一個游戲自動刷副本的腳本

?        let MacroCommand = function() {
            return {
                commandList: [],
                add( command ) {
                    this.commandList.push(command);
                },
                execute () {
                    for(let i = 0,command; command = this.commandList[i++];){
                        command.execute();
                    }
                }
            }
        }
        let startGameCommand = {
            execute() {
                console.log('開始游戲')
            }
        }
        let killGhostCommand = {
            execute() {
                console.log('打怪')
            }
        }
        let giftCommand = {
            execute() {
                console.log("領(lǐng)取獎勵")
            }
        }
        let outGameCommand = {
            execute() {
                console.log("退出游戲")
            }
        }
        let Game = MacroCommand();
        Game.add(startGameCommand);
        Game.add(killGhostCommand);
        Game.add(giftCommand);
        Game.add(outGameCommand);
        Game.execute();  

我們只需要為宏命令對列中添加命令,它會自動執(zhí)行里邊的所有命令。我們只負(fù)責(zé)啟動,其他的就不需要我們管了,我們可以放心的去做其他事情,等待它自己完成。

五. 總結(jié)

命令模式中也提到了傻瓜命令智能命令,它兩的區(qū)別在于傻瓜命令中含有命令的接收者,而智能命令沒有,它直接提供請求。智能命令與策略模式十分相近,只是在使用上不同,策略模式中對象的目標(biāo)相同,只是實現(xiàn)目標(biāo)的算法不同,而命令模式的目標(biāo)更具有散發(fā)性。命令模式還可以完成撤銷、排隊的功能。

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

最新評論