一天一种设计模式-js命令模式

180 阅读2分钟

命令模式中的命令指的是一个执行某些特定事情的指令。

也就是发送者和接收者需要共同约定相同的一件事。

例如,

  1. js面向对象实现:
    var todoOne = {
        add: function () {
            console.log('添加')
        },
        delete:function(){
          console.log('删除')
        }
    }

    var addToFun = function (rec) {
        this.receiver = rec
    }

    addToFun.prototype.excute = function () {
        this.receiver.add();
    }
    
    var deleteFun = function (rec) {
        this.receiver = rec
    }

    addToFun.prototype.excute = function () {
        this.receiver.delete();
    }
    
    var abc = new addToFun(todoOne)
    abc.excute()  // 打印:添加
    var delete = new deleteFun(todoOne)
    delete.excute()   // 打印:删除

这样做有什么用?

假设一个场景, 你在一个外包公司,甲方爸爸命令你去写一个方法。他什么也不关心,只管调。 统一为excute命令,于是上面代码分一下:

//甲方
    
  abc.excute()  // 打印:添加  abc 乙方暴露的方法
  delete.excute()   // 打印:删除  delete 乙方暴露 

//乙方
  var todoOne = {
        add: function () {
            console.log('添加')
        },
        delete:function(){
          console.log('删除')
        }
  }

  var addToFun = function (rec) {
      this.receiver = rec
   }

    addToFun.prototype.excute = function () {
        this.receiver.add();
    }
    
    var deleteFun = function (rec) {
        this.receiver = rec
    }

    addToFun.prototype.excute = function () {
        this.receiver.delete();
    }

苦逼的乙方要写这么多代码,为了各个方法之间的松耦合,还得分开设置构造函数。不然写一起多个if很难看。

  1. js 闭包实现
var btn = document.getElementById('button')

    var todoOne = {
        refresh: function () {
            console.log('执行某个事件')
        }
    }

    function clickTo(btn, fun) {
        btn.onclick = function () {
            fun.excute()
        }
    }

    var RefreshMenuBar = function (receive) {
        return {
            excute: function(){
                receive.refresh()
            }
        }
    }
    
    var RefreshMenuBar2 = RefreshMenuBar(todoOne)
    
    clickTo(btn, RefreshMenuBar2)

这里RefreshMenuBar方法一开始感觉完全是脱裤子放屁不用写, 直接可以在todoOne 里面 refresh 改成 excute。 简单想想还是有好处。 假如 todoOne 这个方法被放在了别的Js中, 你一眼就能知道这个方法要干嘛,refresh传递了函数信息。

如果直接 把refresh改成 excute 方法。不需要 RefreshMenuBar 函数。这种被称为傻瓜命令。

3.宏任务命令模式


//乙方

var todoOne = {
        excute: function () {
            console.log('任务1')
        }
    }

    var todoTwo = {
        excute: function () {
            console.log('任务2')
        }
    }

    var todoThree = {
        excute: function () {
            console.log('任务3')
        }
    }

    var hongrenwu = function () {
        var arr = []
        return {
            add: function (obj) {
                arr.push(obj)
            },
            todo: function () {
                for (let i = 0; i < arr.length; i++) {
                    arr[i].excute()
                }
            }
        }
    }

    var rongji = hongrenwu()
    
    //甲方爸爸代码
    rongji.add(todoOne)
    rongji.add(todoTwo)
    rongji.add(todoThree)
    rongji.todo()  
  1. 总结

    好好想想各种场景,比如 这两个js文件隔着十万八千里,或者时间很久之后什么也不记得了,又或者这个需求需要反复添加,反复迭代,又不能破坏之前的结构来思考为啥别人要这么写。

参考资料: javaScript设计模式与开发实践