命令模式主要应用在需要延迟执行请求、支持撤回的场景中,可能在文本编辑器中有应用,我目前没有使用过,这里就留坑了。
命令模式本质上就是将数据和操作封装为一个对象,实现操作的撤回、延迟等。
这里贴一下 Youtube
一个博主举的 计算器例子。
首先是一个支持加减乘除的计算器:
1class Calculator {
2 constructor() {
3 this.value = 0
4 }
5
6 add(valueToAdd) {
7 this.value = this.value + valueToAdd
8 }
9
10 subtract(valueToSubtract) {
11 this.value = this.value - valueToSubtract
12 }
13
14 multiply(valueToMultiply) {
15 this.value = this.value * valueToMultiply
16 }
17
18 divide(valueToDivide) {
19 this.value = this.value / valueToDivide
20 }
21}
22
23const calculator = new Calculator()
24calculator.add(10)
25console.log(calculator.value) // 10
26calculator.divide(2)
27console.log(calculator.value) // 5
如果需要给计算器增加撤回的功能,就可以使用命令模式了。
我们把每一步操作都封装为一个类作为命令对象,类中包含了操作数和操作方法,然后用一个数组记录所有的命令对象。
1class Calculator {
2 constructor() {
3 this.value = 0
4 this.history = []
5 }
6
7 executeCommand(command) {
8 this.value = command.execute(this.value)
9 this.history.push(command)
10 }
11
12 undo() {
13 const command = this.history.pop()
14 this.value = command.undo(this.value)
15 }
16
17 add(valueToAdd) {
18 this.value = this.value + valueToAdd
19 }
20
21 subtract(valueToSubtract) {
22 this.value = this.value - valueToSubtract
23 }
24
25 multiply(valueToMultiply) {
26 this.value = this.value * valueToMultiply
27 }
28
29 divide(valueToDivide) {
30 this.value = this.value / valueToDivide
31 }
32}
33
34class AddCommand {
35 constructor(valueToAdd) {
36 this.valueToAdd = valueToAdd
37 }
38
39 execute(currentValue) {
40 return currentValue + this.valueToAdd
41 }
42
43 undo(currentValue) {
44 return currentValue - this.valueToAdd
45 }
46}
47
48class SubtractCommand {
49 constructor(valueToSubtract) {
50 this.valueToSubtract = valueToSubtract
51 }
52
53 execute(currentValue) {
54 return currentValue - this.valueToSubtract
55 }
56
57 undo(currentValue) {
58 return currentValue + this.valueToSubtract
59 }
60}
61
62class MultiplyCommand {
63 constructor(valueToMultiply) {
64 this.valueToMultiply = valueToMultiply
65 }
66
67 execute(currentValue) {
68 return currentValue * this.valueToMultiply
69 }
70
71 undo(currentValue) {
72 return currentValue / this.valueToMultiply
73 }
74}
75
76class DivideCommand {
77 constructor(valueToDivide) {
78 this.valueToDivide = valueToDivide
79 }
80
81 execute(currentValue) {
82 return currentValue / this.valueToDivide
83 }
84
85 undo(currentValue) {
86 return currentValue * this.valueToDivide
87 }
88}
89
90const calculator = new Calculator()
91
92calculator.executeCommand(new AddCommand(10))
93calculator.executeCommand(new MultiplyCommand(2))
94console.log(calculator.value) // 20
95calculator.undo()
96console.log(calculator.value) // 10
命令模式的思想比较有意思,将数据和操作封装,实现上在 js
中很简单,我们甚至也不需要 class
,直接通过字面量对象传递也可以。
但实际开发中目前还没用到过,此处留坑。