js常用設(shè)計(jì)模式5-命令模式

命令模式是最簡(jiǎn)單和優(yōu)雅的模式之一,命令模式中的命令(command)指的是一個(gè)執(zhí)行某些特定事情的指令。
設(shè)計(jì)模式的主題總是把不變的事物和變化的事物分離開來,命令模式也不例外。
應(yīng)用場(chǎng)景:請(qǐng)求者需要做一些操作,但是并不需要這些操作是誰來做,只要能被完成就行,請(qǐng)求者和被請(qǐng)求者是松耦合的關(guān)系。
比如點(diǎn)餐時(shí),客人只管點(diǎn)餐,他不需要知道廚師的姓名、聯(lián)系方式,能上菜就行,還要啥自行車。

1,菜單程序

一個(gè)頁面上有10個(gè)按鈕,每個(gè)按鈕都有一個(gè)功能,現(xiàn)在我們來實(shí)現(xiàn)這個(gè)功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <button id="button1">刷新</button>
    <button id="button2">添加</button>
    <button id="button3">刪除</button>
    <script>
        var button1 = document.getElementById('button1')
        var button2 = document.getElementById('button2')
        var button3 = document.getElementById('button3')

        var bindClick = function (button, func) {
            button.onclick = func
        }

        var MenuBar = {
            refresh: function () {
                console.log('刷新頁面')
            }
        }
        var SubMenu = {
            add: function () {
                console.log('增加子菜單')
            },
            del: function () {
                console.log('刪除子菜單')
            }
        }
        //按鈕可以任意添加功能
        bindClick(button1, MenuBar.refresh)
        bindClick(button2, SubMenu.add)
        bindClick(button3, SubMenu.del)

    </script>
</body>
</html>

2,用閉包來實(shí)現(xiàn)

現(xiàn)在我們需要添加一些別的東西,不再是小打小鬧了。
setCommand:用來綁定dom對(duì)象和點(diǎn)擊事件
RefreshMenuBarCommand:專門用來包裝點(diǎn)擊事件的,這個(gè)函數(shù)可以擴(kuò)展,以后說不定要實(shí)現(xiàn)撤銷操作

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button id="button1">刷新</button>
    <button id="button2">添加</button>
    <button id="button3">刪除</button>
    <script>
        //修改成符合策略模式的樣子
        var button1 = document.getElementById('button1')
        var button2 = document.getElementById('button2')
        var button3 = document.getElementById('button3')

        var setCommand = function (button, command) {
            button.onclick = function () {
                command.execute()
            }
        }
        var MenuBar = {
            refresh: function () {
                console.log('刷新菜單界面')
            }
        }
        var RefreshMenuBarCommand = function (receiver) {
            return {
                execute: function () {
                    receiver.refresh()
                }
            }
        }

        var refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar)
        setCommand(button1, refreshMenuBarCommand)

    </script>
</body>
</html>

3,撤銷命令

如果需要撤銷命令怎么辦呢?
我們現(xiàn)在想編寫一個(gè)街頭霸王的小游戲,人物有攻擊、防御、跳躍、蹲下四種操作,每次操作之后都會(huì)保存起來,這樣最后我們可以復(fù)盤。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button id="replay">播放錄像</button>

    <script>

        var player = {
            attack: function () {
                console.log('攻擊')
            },
            defense: function () {
                console.log('防御')
            },
            jump: function () {
                console.log('跳躍')
            },
            crouch: function () {
                console.log('蹲下')
            }
        }
        //創(chuàng)建命令---這個(gè)是命令的執(zhí)行者
        var makeComnand = function (receive, state) {
            if (receive[state]) {
                return receive[state]
            }
        }

        var commands = {
            '119': 'jump',
            '115': 'crouch',
            '97': 'defense',
            '100': 'attack'
        }

        var commandStack = []
        document.onkeypress = function (e) {
            var keyCode = e.keyCode,
                command = makeComnand(player, commands[keyCode])
            if (command) {
                command()
                // 將剛剛執(zhí)行過的命令保存進(jìn)堆棧
                commandStack.push(command)
            }
        }
        // 點(diǎn)擊播放錄像
        document.getElementById('replay').onclick = function () {
            var command
            // 從堆棧里依次取出命令并執(zhí)行
            while (command = commandStack.shift()) {
                command()
            }
        }

    </script>
</body>

</html>

4,小結(jié)

額,這個(gè)我沒啥好說的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容