成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官:說說你對命令模式的理解?應(yīng)用場景?

開發(fā) 前端
命令模式是最簡單和優(yōu)雅的模式之一,命令模式中的命令指的是一個執(zhí)行某些特定事情的指令。

[[434039]]

本文轉(zhuǎn)載自微信公眾號「JS每日一題」,作者灰灰 。轉(zhuǎn)載本文請聯(lián)系JS每日一題公眾號。

一、是什么

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

該模式旨在將函數(shù)的調(diào)用、請求和操作封裝成為一個單一的對象

請求以命令的形式包裹在對象中,并傳給調(diào)用對象。調(diào)用對象尋找可以處理該命令的合適的對象,并把該命令傳給相應(yīng)的對象,該對象執(zhí)行命令

例如在一個快餐店,用戶向服務(wù)員點餐。服務(wù)員將用戶的需求記錄在清單上:

  • 請求者點菜:參數(shù)是菜名(我要什么菜),時間(什么時候要),該需求封裝起來后,如果有變化我可以修改參數(shù)
  • 命令模式將點餐內(nèi)容封裝成為命令對象,命令對象就是填寫的清單
  • 用戶不知道接收者(廚師)是誰,也不知道廚師的炒菜方式與步驟
  • 請求者可以要求修改命令執(zhí)行時間,例如晚1小時再要

二、實現(xiàn)

命令模式由三種角色構(gòu)成:

  • 發(fā)布者 invoker(發(fā)出命令,調(diào)用命令對象,不知道如何執(zhí)行與誰執(zhí)行)
  • 接收者 receiver (提供對應(yīng)接口處理請求,不知道誰發(fā)起請求)
  • 命令對象 command(接收命令,調(diào)用接收者對應(yīng)接口處理發(fā)布者的請求)

 

圖片

 

實現(xiàn)代碼如下:

  1. class Receiver {  // 接收者類 
  2.   execute() { 
  3.     console.log('接收者執(zhí)行請求'); 
  4.   } 
  5.  
  6. class Command {   // 命令對象類 
  7.   constructor(receiver) { 
  8.     this.receiver = receiver; 
  9.   } 
  10.   execute () {    // 調(diào)用接收者對應(yīng)接口執(zhí)行 
  11.     console.log('命令對象->接收者->對應(yīng)接口執(zhí)行'); 
  12.     this.receiver.execute(); 
  13.   } 
  14.  
  15. class Invoker {   // 發(fā)布者類 
  16.   constructor(command) { 
  17.     this.command = command; 
  18.   } 
  19.   invoke() {      // 發(fā)布請求,調(diào)用命令對象 
  20.     console.log('發(fā)布者發(fā)布請求'); 
  21.     this.command.execute(); 
  22.   } 
  23.  
  24. const warehouse = new Receiver();       // 廚師 
  25. const order = new Command(warehouse);   // 訂單 
  26. const client = new Invoker(order);      // 請求者 
  27. client.invoke(); 

三、應(yīng)用場景

命令模式最常見的應(yīng)用場景是:有時候需要向某些對象發(fā)送請求,但是并不知道請求的接收者是誰,也不知道被請求的操作是什么。此時,希望用一種松耦合的方式來設(shè)計程序,使的請求發(fā)送者和請求接收者能夠消除彼此之間的耦合關(guān)系

菜單

現(xiàn)在我們需要實現(xiàn)一個界面,包含很多個按鈕。每個按鈕有不同的功能,我們利用命令模式來完成

  1. <button id="button1"></button> 
  2. <button id="button2"></button> 
  3. <button id="button3"></button> 
  4.  
  5. <script> 
  6.   var button1 = document.getElementById("button1"); 
  7.   var button2 = document.getElementById("button2"); 
  8.   var button3 = document.getElementById("button3"); 
  9. </script> 

然后定義一個setCommand函數(shù),負責將按鈕安裝命令,可以確定的是,點擊按鈕會執(zhí)行某個 command 命令,執(zhí)行命令的動作被約定為調(diào)用 command 對象的 execute() 方法。如下:

  1. var button1 = document.getElementById('button1'
  2. var setCommand = function(button, conmmand) { 
  3.   button.onclick = function() { 
  4.     conmmand.execute() 
  5.   } 

點擊按鈕之后具體行為包括刷新菜單界面、增加子菜單和刪除子菜單等,這幾個功能被分布在 MenuBar 和 SubMenu 這兩個對象中:

  1. var MenuBar = { 
  2.   refresh: function() { 
  3.     console.log('刷新菜單目錄'
  4.   } 
  5. var SubMenu = { 
  6.   addfunction() { 
  7.     console.log('增加子菜單'
  8.   }, 
  9.   del: function(){ 
  10.     console.log('刪除子菜單'); 
  11.   } 

這些功能需要封裝在對應(yīng)的命令類中:

  1. // 刷新菜單目錄命令類 
  2. class RefreshMenuBarCommand { 
  3.     constructor(receiver) { 
  4.         this.receiver = receiver; 
  5.     } 
  6.  
  7.     execute() { 
  8.         this.receiver.refresh(); 
  9.     } 
  10.  
  11. // 增加子菜單命令類 
  12. class AddSubMenuCommand { 
  13.     constructor(receiver) { 
  14.         this.receiver = receiver; 
  15.     } 
  16.  
  17.     execute() { 
  18.         this.receiver.refresh(); 
  19.     } 
  20.  
  21. // '刪除子菜單命令類 
  22. class DelSubMenuCommand { 
  23.     constructor(receiver) { 
  24.         this.receiver = receiver; 
  25.     } 
  26.  
  27.     execute() { 
  28.         this.receiver.refresh(); 
  29.     } 

最后就是把命令接收者傳入到 command 對象中,并且把 command 對象安裝到 button 上面:

  1. var refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar); 
  2. var addSubMenuCommand = new AddSubMenuCommand(SubMenu); 
  3. var delSubMenuCommand = new DelSubMenuCommand(SubMenu); 
  4.  
  5. setCommand(button1, refreshMenuBarCommand); 
  6. setCommand(button2, addSubMenuCommand); 
  7. setCommand(button3, delSubMenuCommand); 

撤銷

命令模式的作用不僅是封裝運算塊,而且可以很方便地給命令對象增加撤銷操作

頁面中有一個 input 文本框和一個 button 按鈕,文本框中可以輸入一些數(shù)字,表示小球移動后的水平位置,小球在用戶點擊按鈕后立刻開始移動,如下:

  1. <div 
  2.   id="ball" 
  3.   style="position: absolute; background: #000; width: 50px; height: 50px" 
  4. ></div> 
  5. 輸入小球移動后的位置:<input id="pos" /> 
  6. <button id="moveBtn">開始移動</button> 
  7. <script> 
  8.   var ball = document.getElementById("ball"); 
  9.   var pos = document.getElementById("pos"); 
  10.   var moveBtn = document.getElementById("moveBtn"); 
  11.   moveBtn.onclick = function () { 
  12.     var animate = new Animate(ball); 
  13.     animate.start("left", pos.value, 1000, "strongEaseOut"); 
  14.   }; 
  15. </script> 

換成命令模式如下:

  1. var ball = document.getElementById("ball"); 
  2. var pos = document.getElementById("pos"); 
  3. var moveBtn = document.getElementById("moveBtn"); 
  4. var MoveCommand = function (receiver, pos) { 
  5.   this.receiver = receiver; 
  6.   this.pos = pos; 
  7. }; 
  8. MoveCommand.prototype.execute = function () { 
  9.   this.receiver.start("left", this.pos, 1000, "strongEaseOut"); 
  10. }; 
  11. var moveCommand; 
  12. moveBtn.onclick = function () { 
  13.   var animate = new Animate(ball); 
  14.   moveCommand = new MoveCommand(animate, pos.value); 
  15.   moveCommand.execute(); 
  16. }; 

撤銷操作的實現(xiàn)一般是給命令對象增加一個名為 unexecude 或者 undo的方法,在該方法里執(zhí)行 execute 的反向操作

在 command.execute 方法讓小球開始真正運動之前,需要先記錄小球的當前位置,在 unexecude 或者 undo 操作中,再讓小球回到剛剛記錄下的位置,代碼如下:

  1. class MoveCommand { 
  2.     constructor(receiver, pos) { 
  3.         this.receiver = receiver; 
  4.         this.pos = pos; 
  5.         this.oldPos = null
  6.     } 
  7.  
  8.     execute() { 
  9.         this.receiver.start('left', this.pos, 1000, 'strongEaseOut'); 
  10.         this.oldPos = this.receiver.dom.getBoundingClientRect()[this.receiver.propertyName];  // 記錄小球開始移動前的位置 
  11.     } 
  12.  
  13.     undo() { 
  14.         this.receiver.start('left', this.oldPos, 1000, 'strongEaseOut'); // 回到小球移動前記錄的位置 
  15.     } 
  16.  
  17. var moveCommand; 
  18. moveBtn.onclick = function () { 
  19.   var animate = new Animate(ball); 
  20.   moveCommand = new MoveCommand(animate, pos.value); moveCommand.execute(); 
  21. }; 
  22. cancelBtn.onclick = function () { 
  23.   moveCommand.undo();// 撤銷命令 
  24. }; 

現(xiàn)在通過命令模式輕松地實現(xiàn)了撤銷功能。如果用普通方法調(diào)用來實現(xiàn),也許需要每次都手工記錄小球的運動軌跡,才能讓它還原到之前的位置

而命令模式中小球的原始位置在小球開始移動前已經(jīng)作為 command 對象的屬性被保存起來,所以只需要再提供一個 undo 方法,并且在 undo方法中讓小球會到剛剛記錄的原始位置就可以

參考文獻

https://www.runoob.com/design-pattern/command-pattern.html

https://juejin.cn/post/6844903673697402888

https://juejin.cn/post/6995474681813811208

 

責任編輯:武曉燕 來源: JS每日一題
相關(guān)推薦

2021-11-05 07:47:56

代理模式對象

2021-11-10 07:47:49

組合模式場景

2021-11-03 14:10:28

工廠模式場景

2021-11-22 23:50:59

責任鏈模式場景

2021-11-11 16:37:05

模板模式方法

2021-09-16 07:52:18

算法應(yīng)用場景

2021-08-16 08:33:26

git

2021-11-04 06:58:32

策略模式面試

2021-09-06 10:51:27

TypeScriptJavaScript

2021-09-28 07:12:09

測試路徑

2021-09-29 07:24:20

場景數(shù)據(jù)

2021-09-10 06:50:03

TypeScript裝飾器應(yīng)用

2021-10-08 09:59:32

冒泡排序場景

2021-10-13 18:01:33

快速排序場景

2021-10-09 10:25:41

排序應(yīng)用場景

2021-09-08 07:49:34

TypeScript 泛型場景

2021-06-01 08:25:06

Node.jsJavaScript運行

2021-05-31 10:35:34

TCPWebSocket協(xié)議

2021-10-18 07:51:39

回溯算法面試

2021-10-12 07:15:02

歸并排序場景
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 在线激情视频 | 日韩av免费在线观看 | 美女张开腿露出尿口 | 日韩中文在线视频 | 久久精品免费看 | 欧美一区二区三区在线观看 | 国产精品一区二区视频 | 亚洲 欧美 精品 | 国产伦精品一区二区三区精品视频 | 国产精品久久久久久久久久 | 美女黄网站视频免费 | 中文字幕韩在线第一页 | 黄色三级免费 | 日韩二区 | 国产精品久久久久久久岛一牛影视 | 美女操网站 | 亚洲视频免费在线观看 | 粉嫩国产精品一区二区在线观看 | 欧美无乱码久久久免费午夜一区 | 在线午夜 | 中文字幕精品视频 | 精品videossex高潮汇编 | 亚洲一区精品在线 | 一二三四在线视频观看社区 | 国产亚洲一区二区精品 | 日日淫 | 亚洲一区二区三区欧美 | 精品一区久久 | 午夜一区二区三区在线观看 | 热99视频 | 国产免费又黄又爽又刺激蜜月al | 视频一区欧美 | 亚洲免费观看视频 | 久久久黄色 | 日韩亚洲欧美一区 | 成人在线观看免费观看 | 久久青 | 中文字幕国产精品 | 天堂久久天堂综合色 | 国产精品视频免费播放 | 亚洲一区在线播放 |