javascript設計模式之命令模式
一. 認識命令模式
所謂命令,也就是指執(zhí)行某些特定事情的指令,就拿喝水的例子來說,喝水執(zhí)行的指令就是將水倒在杯子里,然后端起杯子送入口中,這就是一條命令,無論誰喝水都是這個步驟,我們不關心是誰端起了杯子,也不關心杯子中的水到底是水還是其他東西。我們只關心這個過程,將水倒在杯子中,然后端起杯子送入口中,最后誰喝掉了,喝掉的是飲料還是水不重要。
大家可能聽的有點混,而命令模式最常見的應用場景就是:有時候需要向某些對象發(fā)送請求,但是并不知道請求的接收者是誰,也不知道被請求的操作是什么。此時我們用一種松耦合的方式來設計程序,使得請求發(fā)送者和接收者能夠消除彼此間的耦合關系。
二. 代碼實現(xiàn)-實際應用場景
在實際開發(fā)中團隊協(xié)作是最重要的環(huán)節(jié),假如兩個人分別得到兩個不同的任務,一個人負責頁面中所有的 button 按鈕的美化,另一個人負責實現(xiàn)這些 button 的邏輯,我們在寫 button 邏輯時不知道該 button 最終綁定的是頁面中的哪一個按鈕,也不知道具體點擊該按鈕會發(fā)生什么,此時我們用命令模式來設計,來解開按鈕和負責具體行為對象間的耦合,代碼如下所示。
<script>
let btns = document.querySelectorAll('button');
// 寫一個刷新命令
let refreshCommand = {
execute () {
console.log("刷新頁面");
}
}
// 寫一個登錄按鈕命令
let loginCommand = {
execute () {
console.log("執(zhí)行登錄操作");
}
}
let setCommand = function( button, command) {
button.onclick = function() {
command.execute();
}
}
// 假如第三個按鈕用來負責刷新頁面,第五個用來負責登錄操作
setCommand( btns[2], refreshCommand);
setCommand( btns[4], loginCommand); 分析:我們將點擊按鈕后可能會發(fā)生的事件分別封裝起來,它們中各自有自己的 execute 函數(shù),我們將安裝按鈕功能的函數(shù)封裝到了 setCommand 中,最后根據需求對應安裝各個按鈕的功能便可。
三. 命令模式的撤銷操作
下達一個命令后,我們可能不需要了,想回到下達命令之前的狀態(tài),就需要用到撤銷操作,撤銷操作的實現(xiàn)一般是給命令對象增加一個 undo 或者 unexecute 方法,在其中執(zhí)行 execute 的反向操作。
// 假如寫一個人物向左移的命令
let moveLeftCommand = {
execute() {
console.log("人物向左移動");
}
undo (){
console.log("人物向又移動");
}
}這種是簡單的邏輯實現(xiàn),假如有些撤銷行為無法用執(zhí)行他的反向操作來實現(xiàn),那我們應該怎么辦呢?
帶著這個問題我們學習一種新的達到撤銷的方式,我們用一個棧來記錄每一步命令,想要撤銷,我們只需要重頭開始,從棧中拿出命令來分別執(zhí)行,將最后一次命令刪除即可。如果不刪除最后一次命令依次執(zhí)行,我們又實現(xiàn)了一個新的功能,重播。
這是一個通過 WASD 來控制小球移動的代碼實現(xiàn),我們每次按下一個有效命令時,便會將該命令推入 commandStack 中來記錄小球的變化,當點擊重播時小球會按照之前同樣的軌跡運動。
let role = document.getElementById('role');
let move = {
dom: role,
leftt:0,
top: 0,
up() {
console.log("向上");
this.top -= 10;
this.dom.style.top = this.top + 'px';
},
down(){
console.log("向下");
this.top += 10;
this.dom.style.top = this.top + 'px';
},
left() {
console.log("向左");
this.leftt -= 10;
this.dom.style.left = this.leftt + 'px';
},
right() {
console.log("向右");
this.leftt += 10;
this.dom.style.left = this.leftt + 'px';
}
}
commands = {
"119": "up", // W
"115": "down", // S
"97": "left", // A
"100": "right" // D
};
commandStack = []; // 保存命令的堆棧
let setCommand = function (receiver, state) {
return function() {
receiver[state]();
}
}
document.addEventListener('keypress', (e) => {
let code = e.charCode;
if(!commands[code]) {
return ;
}
let command = setCommand(move, commands[code]);
if( command ) {
command();
commandStack.push( command );
}
})
// 設置重播按鈕
document.getElementById('replay').onclick = function() {
let command;
while(command = commandStack.shift()) {
command();
}
}四. 宏命令
宏命令就是一組命令的集合,通過執(zhí)行宏命令可以一次執(zhí)行一批命令。
通俗來說就是,有一件事你需要重復做,并且做這件事的每一步都是固定不變的,那么我們可以將做這件事情的所有步驟打包起來,只需要啟動,便可以自動完成所有步驟。
需求:實現(xiàn)一個游戲自動刷副本的腳本
? let MacroCommand = function() {
return {
commandList: [],
add( command ) {
this.commandList.push(command);
},
execute () {
for(let i = 0,command; command = this.commandList[i++];){
command.execute();
}
}
}
}
let startGameCommand = {
execute() {
console.log('開始游戲')
}
}
let killGhostCommand = {
execute() {
console.log('打怪')
}
}
let giftCommand = {
execute() {
console.log("領取獎勵")
}
}
let outGameCommand = {
execute() {
console.log("退出游戲")
}
}
let Game = MacroCommand();
Game.add(startGameCommand);
Game.add(killGhostCommand);
Game.add(giftCommand);
Game.add(outGameCommand);
Game.execute(); 我們只需要為宏命令對列中添加命令,它會自動執(zhí)行里邊的所有命令。我們只負責啟動,其他的就不需要我們管了,我們可以放心的去做其他事情,等待它自己完成。
五. 總結
命令模式中也提到了傻瓜命令和智能命令,它兩的區(qū)別在于傻瓜命令中含有命令的接收者,而智能命令沒有,它直接提供請求。智能命令與策略模式十分相近,只是在使用上不同,策略模式中對象的目標相同,只是實現(xiàn)目標的算法不同,而命令模式的目標更具有散發(fā)性。命令模式還可以完成撤銷、排隊的功能。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
JavaScript Math.ceil 方法(對數(shù)值向上取整)
js Math.ceil用于對數(shù)值向上取整,即得到大于或等于該數(shù)值的最小整數(shù),需要的朋友可以參考下2015-01-01
javascript SpiderMonkey中的函數(shù)序列化如何進行
JavaScript中如何進行函數(shù)序列化,函數(shù)序列化的作用是什么?本文將介紹SpiderMonkey中的函數(shù)序列化,有需要的朋友可以參考下2012-12-12
javascript replace()第二個參數(shù)為函數(shù)時的參數(shù)用法
replace()函數(shù)具有替換功能,它可以具有兩個參數(shù),第一個參數(shù)可以是要被替換的字符串或者匹配要被替換字符串的正則表達式,第二個參數(shù)可以是替換文本或者一個函數(shù),下面看一下關于replace()函數(shù)的幾個代碼實例2016-12-12
JavaScript中用于生成隨機數(shù)的Math.random()方法
這篇文章主要介紹了JavaScript中用于生成隨機數(shù)的Math.random()方法,是JS入門學習中的基礎知識,需要的朋友可以參考下2015-06-06

