不直接调用类的内部方法,而是通过给“指令函数”传递参数,由“指令函数”来调用类的内部方法,命令模式的由来其实是回调函数(callback)的代替品

假设场景

有10个button、每个button所做的事情不一样、目前也不知道具体做什么、接到的任务就是A去写10个按钮、B去写这10个按钮的业务、如果通过命令模式去编写呢?

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <button id="button1">刷新目前</button>
  11. <button id="button2">添加目前</button>
  12. <button id="button3">删除目前</button>
  13. </body>
  14. </html>
  15. <script>
  16. // 封装行为
  17. class MenuBar{
  18. constructor(){}
  19. refresh(){
  20. console.log('刷新菜单目录')
  21. }
  22. }
  23. class SubMenu{
  24. constructor(){}
  25. add(){
  26. console.log('添加菜单目录')
  27. }
  28. del(){
  29. console.log('删除菜单')
  30. }
  31. }
  32. // 把行为封装在命令类中
  33. class RefreshMenuBarCommand{
  34. constructor(receiver){
  35. this.receiver = receiver
  36. }
  37. execute(){
  38. this.receiver.refresh()
  39. }
  40. }
  41. class AddSubmenuCommand{
  42. constructor(receiver){
  43. this.receiver = receiver
  44. }
  45. execute(){
  46. this.receiver.add()
  47. }
  48. }
  49. class DelSubmenuCommand{
  50. constructor(receiver){
  51. this.receiver = receiver
  52. }
  53. execute(){
  54. this.receiver.del()
  55. }
  56. }
  57. function setCommand(button, command){
  58. button.onclick = function(){
  59. command.execute()
  60. }
  61. }
  62. let button1 = document.getElementById('button1')
  63. let button2 = document.getElementById('button2')
  64. let button3 = document.getElementById('button3')
  65. setCommand(button1, new RefreshMenuBarCommand(new MenuBar()))
  66. setCommand(button2, new AddSubmenuCommand(new SubMenu()))
  67. setCommand(button3, new DelSubmenuCommand(new SubMenu()))
  68. </script>

总结

优点

  • 降低耦合,将请求者和请求接收者进行解耦
  • 扩展性高、如果需要爱扩展新命令,直接定义命令对象即可,如果要执行一组命令、发送一组命令给接收者就好

    缺点

  • 增加复杂度