《JavaScript设计模式与开发实践》——学习笔记(命令模式)

132 阅读1分钟

核心概念

命令模式就是将一系列操作封装成一个命令对象,再将其交由接受者执行。从而解除了请求者与接收者的耦合关系。用代码表示大概就是下面的样子:

const dog = {
  bark: () => {
    console.log('bark')
  },
}

// 构建命令对象的方法
const createCommand = receiver => {
  return {
    execute() {
      receiver.bark()
    },
  }
}

// 构建一个狗叫的命令对象
const barkCommand = createCommand(dog)

// 请求发送
button.onclick = () => {
  barkCommand.execute()
}

这看起来像只是把简单的问题复杂化了,因为上面的功能完全可以利用下方更简洁的代码实现:

const dog = {
  bark: () => {
    console.log('bark')
  },
}

// 请求发送
button.onclick = () => {
  dog.bark()
}

那为何我们需要命令模式?为何要多增加一步命令对象的构建?

原因就是构建出来的命令对象拥有更长的生命周期。

命令对象除了拥有execute方法去执行特定的操作,也可以用于undo方法去撤销已经执行的操作(这需要在execute额外记录一些初始数据)。我们甚至可以将每个命令对象执行完成后压入一个任务的堆栈中,去实现一系列动作的复现与撤销。

扩展用法

对于一些需要频繁变换的事件行为,我们还能用命令对象的execute方法引用的变更,来代替频繁的事件挂载与移除,从而减少系统开销。就像下面的例子一样:

const sayHi = () => {
  console.log('hi')
}
const sayHello = () => {
  console.log('hello')
}
// 需要移除再挂载
button.addEventListener('click', sayHi)
button.removeEventListener('click', sayHi)
button.addEventListener('click', sayHello)

const sayCommand = {
  execute: () => {
    console.log('hi')
  },
}

// 只需挂载一次
button.addEventListener('click',() => {
  sayCommand.execute()
})

sayCommand.execute = () => {
  console.log('hello')
}