《JavaScript設計模式與開發實踐》模式篇(6)—— 命令模式

嗨呀豆豆呢發表於2018-12-14

命令模式是最簡單和優雅的模式之一,命令模式中的命令(command)指的是一個執行某些特定事情的指令。

應用場景

 
 
 
 
有時候需要向某些物件傳送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是什麼。此時希望用一種鬆耦合的方式來設計程式,使得請求傳送者和請求接收者能夠消除彼此之間的耦合關係。

  • 選單案例

 
 
 
 
假設我們正在編寫一個使用者介面程式,該使用者介面上至少有數十個 Button 按鈕。因為專案比較複雜,所以我們決定讓某個程式設計師負責繪製這些按鈕,而另外一些程式設計師則負責編寫點選按鈕後的具體行為,這些行為都將被封裝在物件裡。

 
 
 
 
在大型專案開發中,這是很正常的分工。對於繪製按鈕的程式設計師來說,他完全不知道某個按鈕未來將用來做什麼,可能用來重新整理選單介面,也可能用來增加一些子選單,他只知道點選這個 按鈕會發生某些事情。那麼當完成這個按鈕的繪製之後,應該如何給它繫結onclick 事件呢?

 
 
 
 
我們很快可以找到在這裡運用命令模式的理由:點選了按鈕之後,必須向某些負責具體行為的物件傳送請求,這些物件就是請求的接收者。但是目前並不知道接收者是什麼物件,也不知道接收者究竟會做什麼。此時我們需要藉助命令物件的幫助,以便解開按鈕和負責具體行為物件之間的耦合。

  • 程式碼實現
 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 );
複製程式碼
  • 撤銷命令

 
 
 
 
命令模式的作用不僅是封裝運算塊,而且可以很方便地給命令物件增加撤銷操作。現在頁面上有個小球,點選移動按鈕和撤銷按鈕可以實現移動和撤銷的操作。

  • 程式碼實現
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。

  • 程式碼實現
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();
複製程式碼

系列文章:

《JavaScript設計模式與開發實踐》最全知識點彙總大全

來源:https://juejin.im/post/5c1379cd6fb9a049c2325166

相關文章