命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。
使用背景
解耦请求发送者和请求接收者:当需要解耦请求发送者和请求接收者时,可以使用命令模式。命令模式将请求封装成一个独立的对象,从而使得请求发送者和接收者之间的关系松耦合,请求发送者不需要知道请求的具体接收者。
支持撤销和重做操作:命令模式可以很容易地支持撤销和重做操作。通过将请求封装成对象,可以在执行请求前将其记录下来,从而可以轻松地撤销或重做这些请求。
支持事务:命令模式可以支持事务操作。将一系列操作封装成一个命令对象,并且在执行时保证这些操作要么全部成功执行,要么全部不执行。
日志和回滚操作:命令模式可以用于记录操作日志,并且在需要时执行回滚操作。通过将操作封装成命令对象,并将这些命令对象保存到日志中,可以在需要时执行这些命令对象来回滚操作。
队列请求:命令模式可以用于实现队列请求。将请求封装成命令对象,并将这些命令对象存储在队列中,然后按照队列顺序执行这些命令对象。
实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| package main
import "fmt"
type Command interface { Execute() Undo() }
type Editor struct { content string }
type AddTextCommand struct { editor *Editor text string }
func (a *AddTextCommand) Execute() { a.editor.content += a.text }
func (a *AddTextCommand) Undo() { a.editor.content = a.editor.content[:len(a.editor.content)-len(a.text)] }
type UndoRedoHistory struct { commands []Command }
func (h *UndoRedoHistory) ExecuteCommand(command Command) { command.Execute() h.commands = append(h.commands, command) }
func (h *UndoRedoHistory) Undo() { if len(h.commands) == 0 { return } lastCommand := h.commands[len(h.commands)-1] lastCommand.Undo() h.commands = h.commands[:len(h.commands)-1] }
func main() { editor := &Editor{} history := &UndoRedoHistory{}
addTextCommand1 := &AddTextCommand{editor, "Hello, "} history.ExecuteCommand(addTextCommand1)
addTextCommand2 := &AddTextCommand{editor, "world!"} history.ExecuteCommand(addTextCommand2)
fmt.Println("当前内容:", editor.content)
history.Undo() fmt.Println("撤销后内容:", editor.content)
history.ExecuteCommand(addTextCommand2) fmt.Println("重做后内容:", editor.content) }
|
结语
命令模式可以实现命令的执行和撤销操作,同时使得命令发送者和接收者之间的解耦。通过将命令封装成对象,我们可以很容易地实现撤销、重做、事务等功能,并且可以更加灵活地管理命令的执行顺序。