https://mp.weixin.qq.com/s/gyB93m0wpCSI8YFwSxrhkw
https://www.yuque.com/wubinhp/uxiv5i/ozc2c5#DtfZS

命令模式的本质是对命令进行封装,将命令的发送者和接受者解耦。

常见形式

  1. // 设置命令
  2. const setCommand = (button, command) => {
  3. button.onclick = () => {
  4. command.execute();
  5. };
  6. };
  7. // 业务逻辑
  8. const MenuBar = {
  9. refresh: () => {
  10. console.log("refresh");
  11. },
  12. };
  13. const RefreshMenuBarCommand = (receiver) => {
  14. return {
  15. execute: () => {
  16. receiver.refresh();
  17. },
  18. };
  19. };
  20. const refreshMenuBarCommand = RefreshMenuBarCommand(MenuBar);
  21. // 绑定按钮和命令
  22. setCommand(refreshBtn, refreshMenuBarCommand);

JS的简单用法

  1. const setCommand = (button, command) => {
  2. button.onclick = () => {
  3. command.execute();
  4. };
  5. };
  6. // 业务逻辑
  7. const MenuBar = {
  8. refresh: () => {
  9. console.log("refresh");
  10. },
  11. };
  12. setCommand(refreshBtn, MenuBar.refresh);

js 将函数作为一等公民,运算逻辑不一定要封装在 command.execute方法中然后传递 command对象,可以直接将函数进行传递。

引入undo/redo

实现数字的加减和undo/redo

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <body>
  4. <button id="add">add</button>
  5. <button id="del">del</button>
  6. <button id="undo">undo</button>
  7. <button id="redo">redo</button>
  8. <!-- <script src="./command.js"></script>
  9. -->
  10. <script>
  11. let num = 0;
  12. const addCommand = {
  13. execute: () => {
  14. num++;
  15. console.log("+:", num);
  16. },
  17. undo: () => {
  18. num--;
  19. console.log("undo:", num);
  20. },
  21. };
  22. const delCommand = {
  23. execute: () => {
  24. num--;
  25. console.log("-:", num);
  26. },
  27. undo: () => {
  28. num++;
  29. console.log("undo:", num);
  30. },
  31. };
  32. const commandManager = {
  33. undoStack: [],
  34. redoStack: [],
  35. executeCommand(command) {
  36. this.redoStack = [];
  37. this.undoStack.push(command);
  38. command.execute();
  39. },
  40. undo() {
  41. if (this.undoStack.length === 0) return;
  42. const lastCommand = this.undoStack.pop();
  43. lastCommand.undo();
  44. this.redoStack.push(lastCommand);
  45. },
  46. redo() {
  47. if (this.redoStack.length === 0) return;
  48. const lastCommand = this.redoStack.pop();
  49. lastCommand.execute();
  50. this.undoStack.push(lastCommand);
  51. },
  52. };
  53. const setCommand = (button, command) => {
  54. if (typeof command === "object") {
  55. button.onclick = function () {
  56. commandManager.executeCommand(command);
  57. };
  58. } else {
  59. button.onclick = function () {
  60. command.call(commandManager);
  61. };
  62. }
  63. };
  64. const addBtn = document.getElementById("add");
  65. const delBtn = document.getElementById("del");
  66. const undoBtn = document.getElementById("undo");
  67. const redoBtn = document.getElementById("redo");
  68. setCommand(addBtn, addCommand);
  69. setCommand(delBtn, delCommand);
  70. setCommand(undoBtn, commandManager.undo);
  71. setCommand(redoBtn, commandManager.redo);
  72. </script>
  73. </body>
  74. </html>