命令模式旨在将方法调用、请求或操作封装到单一对象中,从而根据我们不同的请求对客户进行参数化和传递可供执行的方法调用。它将调用操作的对象和知道如何实现此操作的对象解藕。
场景模拟
假设一个页面有A、B、C、D、E五个按钮,A、B、C点击后都会调用后端服务urlA来获取数据,只不过传递的参数不同,D、E会调用urlB来获取数据,同样参数不同。
如果不使用命令模式,我们可能会这么写代码:
<Button onclick="handleclick1()">A</Button>
<Button onclick="handleclick2()">B</Button>
<Button onclick="handleclick3()">C</Button>
<Button onclick="handleclick4()">D</Button>
<Button onclick="handleclick5()">E</Button>
// 重复代码过多,如果服务端要求增加一个通用参数,或者从get改成post,则所有的click事件都需要进行修改
// 如果增加一个按钮F,则需要额外增加一个funciton来对应click事件
function handleclick1 () {
$.get(urlA, {data: 'A'})
}
function handleclick2 () {
$.get(urlA, {data: 'B'})
}
function handleclick3 () {
$.get(urlA, {data: 'C'})
}
function handleclick4 () {
$.get(urlB, {data: 'D'})
}
function handleclick5 () {
$.get(urlB, {data: 'E'})
}
如果使用命令模式:那么意味着,我们希望click事件只是发出一个统一的命令,而由统一的Command指令类分发和处理具体的实现:
<Button onclick="handleclick('push', 'A')">A</Button>
<Button onclick="handleclick('push', 'B')">B</Button>
<Button onclick="handleclick('push', 'C')">C</Button>
<Button onclick="handleclick('pull', 'D')">D</Button>
<Button onclick="handleclick('pull', 'E')">E</Button>
// 使用指令类 抽象指令方法 进行指令分发
var Command = {
execute: function (cmd, param) {
Command[cmd].(param)
},
push: function (param) {
$.get(urlA, param)
},
pull: function (param) {
$.get(urlB, param)
}
}
function handleclick (cmd, param) {
// 点击事件调用统一的指令类
Command.execute(cmd, param)
}
优点
- 调用者无需关心具体的指令实现,调用者角色与接收者角色之间没有任何依赖关系。
- 新增调用者无需求改指令代码,如:增加一个类似行为的按钮,只需要增加一个Button即可,无需对js代码进行修改。
- 新增一个指令很容易: Command.newCommand = function (param) {}。
缺点
如果同一级指令过多,则指令类会变的过于庞大不易于管理。