命令模式中的命令(command)指的是一个执行某些特定事件的指令,最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。
举个🌰
代码实现
// 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]()
}
}
除了简单的接受请求,命令模式还可以完成撤销和重做功能 再举个🌰
代码实现
// 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'
}