js设计模式

js常用设计模式5-命令模式

2021-01-17  本文已影响0人  青色琉璃

命令模式是最简单和优雅的模式之一,命令模式中的命令(command)指的是一个执行某些特定事情的指令。
设计模式的主题总是把不变的事物和变化的事物分离开来,命令模式也不例外。
应用场景:请求者需要做一些操作,但是并不需要这些操作是谁来做,只要能被完成就行,请求者和被请求者是松耦合的关系。
比如点餐时,客人只管点餐,他不需要知道厨师的姓名、联系方式,能上菜就行,还要啥自行车。

1,菜单程序

一个页面上有10个按钮,每个按钮都有一个功能,现在我们来实现这个功能:

<!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,用闭包来实现

现在我们需要添加一些别的东西,不再是小打小闹了。
setCommand:用来绑定dom对象和点击事件
RefreshMenuBarCommand:专门用来包装点击事件的,这个函数可以扩展,以后说不定要实现撤销操作

<!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,撤销命令

如果需要撤销命令怎么办呢?
我们现在想编写一个街头霸王的小游戏,人物有攻击、防御、跳跃、蹲下四种操作,每次操作之后都会保存起来,这样最后我们可以复盘。

<!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('蹲下')
            }
        }
        //创建命令---这个是命令的执行者
        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()
                // 将刚刚执行过的命令保存进堆栈
                commandStack.push(command)
            }
        }
        // 点击播放录像
        document.getElementById('replay').onclick = function () {
            var command
            // 从堆栈里依次取出命令并执行
            while (command = commandStack.shift()) {
                command()
            }
        }

    </script>
</body>

</html>

4,小结

额,这个我没啥好说的

上一篇下一篇

猜你喜欢

热点阅读