命令模式
定义
在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。1
我们来看下命令模式的定义,明显的关键词我们都用黑体字标注出来了,行为的请求者和执行者是关系对象,关键是要使“紧耦合”变为“松耦合”
使用场景
命令模式最常见的运用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接受者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接受者能够消除彼此之间的耦合关系
模式优点
- 降低对象之间的耦合度。
- 新的命令可以很容易地加入到系统中。
- 可以比较容易地设计一个组合命令。
- 调用同一方法实现不同的功能
举个例子
现在的生活中,点外卖便利了我们的生活,订餐的时候我们只需要再平台上下单,可以不用知道是哪个究竟厨师的长相和联系方式,也不需要关系做菜的步骤和方法。这里平台的订单就是把我们的请求都集中的command对象,订单在平台中通过程序被传递到商户中,类似于我们到饭店吃饭,我们也无需知道厨师是谁,因为有服务员把我们的点的单子记录下来传到厨师手中,这样就解开了请求者和接收者之间的耦合关系
JavaScript中的命令模式
现在我们通过简单js代码的模拟下这个点单的程序:
<button id='addBtn'>添加</button>
<button id='delBtn'>删除</button>
let Menu = {
add: function(dishName) {
console.log('添加' + dishName)
}
delete: function(dishName) {
console.log('删除' + dishName)
}
}
let actionFun = function (btn, action) {
btn.onclick = action;
}
actionFun('addBtn', Menu.add)
actionFun('addBtn', Menu.del)
这样用简单的几行代码实现一个添加删除的功能,现在我们继续看下使用js模拟传统面向对象语言的命令模式,看看有什么不同
JavaScript实现传统的命令模式
// 建命令
let Command = function (receiver) {
this.receiver = receiver
}
Command.prototype.execute = function () {
this.receiver.doCommand()
}
// 接收者 商家
let AddDish = function(dishName) {
AddDish.prototype.doCommand = function () {
console.log('添加' + dishName + '成功')
}
}
let DelDish = function(dishName) {
DelDish.prototype.doCommand = function () {
console.log('删除' + dishName + '成功')
}
}
// 请求者 顾客
let Custormer = function(addDishCommand, delDishCommand) {
this.addDishCommand = addDishCommand;
this.delDishCommand = delDishCommand;
}
Custormer.prototype.addDish = function() {
this.addDishCommand.execute()
}
Custormer.prototype.delDish = function() {
this.delDishCommand.execute()
}
// 平台 执行
let addDishCommand = new Command(new AddDish('番茄炒鸡蛋'))
let delDishCommand = new Command(new DelDish('牛腩炖土豆'))
let custormer = new Custormer(addDishCommand, delDishCommand)
custormer.addDish();
custormer.delDish();
乍一看,这个过程好像没什么好处,似乎是给对象加了名为execute的方法,并且command和接收者的存在复杂了我们前面的过程?传统的命令模式将过程是的请求调用封装在command的execute方法中,通过封装方法调用,把运算块包装,command对象可以被随意传递,因此在调用命令的时候,顾客(Client)不需要关心事情是如何进行的,这样就达到了对请求者和接收者之间解耦的目的
小结
- 命令模式的本质是对命令的封装,将发出的命令和执行命令的动作分隔开
- 对于命令模式而言,每个命令都是一次操作,请求者发起一个请求,需要执行一个操作,接收者收到命令时同样要执行
- 命令模式允许请求发起者和请求接受者是黑盒模式,不必知道对方的接口是什么,更不必关心其中的操作过程
- 命令模式使得请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递
- 命令模式引入了抽象命令接口,只有实现了抽象命令接口的具体命令才能与接受者相关联
设计模式-百度百科[引用日期2019-06-16] ↩︎