命令模式是最簡單和優雅的模式之一,命令模式中的命令(command)指的是一個執行某些特定事情的指令。程序員
有時候須要向某些對象發送請求,可是並不知道請求的接收者是誰,也不知道被請求的操做是什麼。此時但願用一種鬆耦合的方式來設計程序,使得請求發送者和請求接收者可以消除彼此之間的耦合關係。設計模式
假設咱們正在編寫一個用戶界面程序,該用戶界面上至少有數十個 Button 按鈕。由於項目比較複雜,因此咱們決定讓某個程序員負責繪製這些按鈕,而另一些程序員則負責編寫點擊按鈕後的具體行爲,這些行爲都將被封裝在對象裏。bash
在大型項目開發中,這是很正常的分工。對於繪製按鈕的程序員來講,他徹底不知道某個按鈕將來將用來作什麼,可能用來刷新菜單界面,也可能用來增長一些子菜單,他只知道點擊這個 按鈕會發生某些事情。那麼當完成這個按鈕的繪製以後,應該如何給它綁定onclick 事件呢?dom
咱們很快能夠找到在這裏運用命令模式的理由:點擊了按鈕以後,必須向某些負責具體行爲的對象發送請求,這些對象就是請求的接收者。可是目前並不知道接收者是什麼對象,也不知道接收者究竟會作什麼。此時咱們須要藉助命令對象的幫助,以便解開按鈕和負責具體行爲對象之間的耦合。post
var RefreshMenuBarCommand = function( receiver ){
return {
execute: function(){
receiver.refresh();
}
}
};
var setCommand = function( button, command ){
button.onclick = function(){
command.execute();
}
};
var refreshMenuBarCommand = RefreshMenuBarCommand( MenuBar );
setCommand( button1, refreshMenuBarCommand );
複製代碼
命令模式的做用不只是封裝運算塊,並且能夠很方便地給命令對象增長撤銷操做。如今頁面上有個小球,點擊移動按鈕和撤銷按鈕能夠實現移動和撤銷的操做。ui
var MoveCommand = function( receiver, pos ){
this.receiver = receiver;
this.pos = pos;
this.oldPos = null;
};
MoveCommand.prototype.execute = function(){
this.receiver.start( 'left', this.pos, 1000, 'strongEaseOut' );
this.oldPos = this.receiver.dom.getBoundingClientRect([this.receiver.propertyName ]; // 記錄小球開始移動前的位置
};
MoveCommand.prototype.undo = function(){
this.receiver.start( 'left', this.oldPos, 1000, 'strongEaseOut' ); // 回到小球移動前記錄的位置
};
var moveCommand;
moveBtn.onclick = function(){
var animate = new Animate( ball );
moveCommand = new MoveCommand( animate, pos.value );
moveCommand.execute();
};
cancelBtn.onclick = function(){
moveCommand.undo();
};
複製代碼
宏命令是一組命令的集合,經過執行宏命令的方式,能夠一次執行一批命令。想象一下,家裏有一個萬能遙控器,天天回家的時候,只要按一個特別的按鈕,它就會幫咱們關上房間門,順便打開電腦並登陸 QQ。this
var closeDoorCommand = {
execute: function(){
console.log( '關門' );
}
};
var openPcCommand = {
execute: function(){
console.log( '開電腦' );
}
};
var openQQCommand = {
execute: function(){
console.log( '登陸 QQ' );
}
};
var MacroCommand = function(){
return {
commandsList: [],
add: function( command ){
this.commandsList.push( command );
},
execute: function(){
for ( var i = 0, command; command = this.commandsList[ i++ ]; ){
command.execute();
}
}
}
};
var macroCommand = MacroCommand();
macroCommand.add( closeDoorCommand );
macroCommand.add( openPcCommand );
macroCommand.add( openQQCommand );
macroCommand.execute();
複製代碼