命令模式

126 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

导言

命令模式可以分为命令发送方和接收方,发送方发出指令,接收方做出对应的执行动作。这么描述的话,有没有感觉命令模式和观察者模式(发布-订阅模式)很像,发送方和接收方不就是对应的发布和订阅方式。还有的人说,命令模式和策略模式也很类似,因为发送方可能有多种不同命令,接收方就对应需要不同的策略来执行。

两种对比都有一定的道理吧,但既然有各自的设计名称,那彼此间肯定也存在一定的边界。我们再看个生活中很常见的例子:开空调。现在技术越来越进步,越来越智能,在空调刚问世不就的时候,开空调只能通过按键,再往后发展,不仅可以通过按键操作,还能通过遥控器远程开关和调节温度,风力等来控制室内温度,这还不够,我们现在还能通过商家开发的APP来替换遥控器进行操作,是不是更方面了呢?当然是。我们再想想,按键,遥控器,APP其实就相当于命令的发送方,空调就是命令的接收方,空调开关,冷热,温度,风力等等包含了不同的命令。我们仅以空调开关来说,空调的开和关的方法肯定是低耦合的,中间会存在一个方法,分别来接收按键开和关,遥控器的开和关,APP的开和关,再调独立的开和关的方法,这里又用到了适配器模式,可见设计模式之间是环环相扣的,不能完全独立存在,可能会相互包容,你中有我,我中有你。

开关空调

我们先定义个空调对象,包含开和关方法,在通过不同对象发送命令,携带发送方信息,当然空调接收方仅简单直接执行了对应的命令,省略了中间的适配过程。

let airConditioner = {
  open: function (way) {
    console.log('通过' + way + '把空调打开了')
  },
  close: function (way) {
    console.log('通过' + way + '把空调关了')
  }
}
let tap = {
  way: '按键'
}
let remote = {
  way: '遥控器'
}
let app = {
  way: 'APP'
}
airConditioner.open.call(tap, tap.way) // 通过按键把空调打开了
airConditioner.close.call(tap, tap.way) // 通过按键把空调关了
airConditioner.open.call(remote, remote.way) // 通过遥控器把空调打开了
airConditioner.open.call(app, app.way) // 通过APP把空调打开了

还是回到导言部分的对比,这个适合用观察者模式来写吗?可以,但似乎不妥,观察者模式需要先注册被观察者对象,观察者模式和命令模式发送接收双方正好角色相反,像我们主动的行为,更适合用命令模式。还有策略模式,策略模式一般更适合于发起者是一个对象,一个对象的多种行为,而命令模式可以是由多个不同对象发起,接收方也可以是多个不同的对应执行。