js设计模式-命令模式

228 阅读1分钟

命令模式中的命令(command)指的是一个执行某些特定事件的指令,最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。

举个🌰 image.png

代码实现

// main.vue
<template>
  <button @click="Order('西红柿炒鸡蛋')">顾客1</button>
  <button @click="Order('黄瓜炒肉')">顾客2</button>
  <button @click="Order('辣子鸡丁')">顾客3</button>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import {cook, cookCommands, cookCommand} from '@/utils/cook'
export default defineComponent({
  methods: {
    Order(food) {
      const cmd = cookCommand(cook, cookCommands[food])
      cmd()
    }
  }
})
</script>
// cook.js
export const cook = new class Cook {
  doCook1() {
      console.log('西红柿炒鸡蛋完成了')
  }
  doCook2() {
      console.log('黄瓜炒肉完成了')
  }
  doCook3() {
      console.log('辣子鸡丁完成了')
    }
}

export const cookCommands= {
  '西红柿炒鸡蛋': 'doCook1',
  '黄瓜炒肉': 'doCook2',
  '辣子鸡丁': 'doCook3',
}


export const cookCommand = function(receiver, food) {
  if (!receiver[food]) return
  return function(){
    receiver[food]()
  }
}

除了简单的接受请求,命令模式还可以完成撤销和重做功能 再举个🌰

image.png

代码实现

// main.vue
<template>
<button @click="replay">播放录像</button>
</template>

<script lang="ts">
import {Ryu, makeCommand, commands} from '@/utils/ryu'
import { defineComponent } from 'vue'
export default defineComponent({
  setup() {
    const commandStack:Function[] = [];
    document.onkeyup = (ev) => {
      const keycode = ev.key;
      const command = makeCommand(Ryu, commands[keycode])
      if (command) {
        command();
        commandStack.push(command)
      }
    }
    return {
      commandStack,
    }
  },
  methods: {
    replay() {
      let command = null;
      while(command = this.commandStack.shift()) {
        command()
      }
    }
  }
})
</script>
// ryu.js
export const Ryu = new class Ryu {
  attack() {
    console.log('攻击')
  }
  defense() {
    console.log('防御')
  }
  jump() {
    console.log('跳跃')
  }
  crouch() {
    console.log('蹲下')
  }
}


export const makeCommand = (receiver, state) => {
  if (!receiver[state]) return
  return function() {
    receiver[state]()
  }
}
export const commands = {
  'w': 'jump',
  's': 'crouch',
  'a': 'defense',
  'd': 'attack'
}