核心概念
命令模式就是将一系列操作封装成一个命令对象,再将其交由接受者执行。从而解除了请求者与接收者的耦合关系。用代码表示大概就是下面的样子:
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')
}