命令模式通过封装请求为对象实现撤销功能,Go中定义Command接口含Execute和Undo方法,以TextEditor为接收者处理插入删除操作,InsertCommand和DeleteCommand保存执行上下文并实现正向执行与反向撤销逻辑,CommandHistory维护命令栈管理执行与撤销顺序,客户端按序执行命令并可逐级撤销,支持多步回退且符合开闭原则,便于扩展重做与组合命令。

在Go语言中,命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。使用命令模式实现撤销功能,可以让程序支持操作的回退,比如文本编辑器中的“撤销键入”、“撤销删除”等场景。
命令模式通常包含以下几个角色:
首先定义一个命令接口,包含Execute()和Undo()两个方法:
type Command interface {
Execute()
Undo()
}
假设我们要实现一个简单的文本编辑器,支持插入文本和删除文本,并能撤销这些操作。
立即学习“go语言免费学习笔记(深入)”;
接收者是实际处理数据的对象:
type TextEditor struct {
content string
}
<p>func (t *TextEditor) Insert(text string) {
t.content += text
}</p><p>func (t *TextEditor) Delete(length int) {
if length >= len(t.content) {
t.content = ""
} else {
t.content = t.content[:len(t.content)-length]
}
}</p><p>func (t *TextEditor) GetContent() string {
return t.content
}</p>每个操作都封装成一个命令对象,保存执行所需的数据,以便撤销时恢复状态。
插入命令:
type InsertCommand struct {
editor *TextEditor
text string
}
<p>func NewInsertCommand(editor <em>TextEditor, text string) </em>InsertCommand {
return &InsertCommand{editor: editor, text: text}
}</p><p>func (c *InsertCommand) Execute() {
c.editor.Insert(c.text)
}</p><p>func (c *InsertCommand) Undo() {
// 撤销插入:删除最后插入的内容
c.editor.Delete(len(c.text))
}</p>删除命令:
type DeleteCommand struct {
editor *TextEditor
deleted string // 保存被删除的内容,用于撤销
}
<p>func NewDeleteCommand(editor <em>TextEditor, length int) </em>DeleteCommand {
end := len(editor.content)
start := end - length
if start < 0 {
start = 0
}
deleted := editor.content[start:end]
return &DeleteCommand{
editor: editor,
deleted: deleted,
}
}</p><p>func (c *DeleteCommand) Execute() {
c.editor.Delete(len(c.deleted))
}</p><p>func (c *DeleteCommand) Undo() {
// 撤销删除:重新插入之前删掉的内容
c.editor.Insert(c.deleted)
}</p>命令调用者负责执行命令并维护历史记录:
type CommandHistory struct {
history []Command
index int // 当前位置,支持未来可能的重做
}
<p>func NewCommandHistory() *CommandHistory {
return &CommandHistory{
history: make([]Command, 0),
index: -1,
}
}</p><p>func (ch *CommandHistory) Execute(command Command) {
// 执行新命令时,丢弃“未来”的命令(重做部分)
ch.history = ch.history[:ch.index+1]
ch.index++
ch.history = append(ch.history, command)
command.Execute()
}</p><p>func (ch *CommandHistory) Undo() {
if ch.index >= 0 {
command := ch.history[ch.index]
command.Undo()
ch.index--
}
}</p>现在将所有组件组合起来:
func main() {
editor := &TextEditor{}
history := NewCommandHistory()
<pre class='brush:php;toolbar:false;'>// 插入 "Hello"
cmd1 := NewInsertCommand(editor, "Hello")
history.Execute(cmd1)
fmt.Println("After insert 'Hello':", editor.GetContent()) // Hello
// 插入 " World"
cmd2 := NewInsertCommand(editor, " World")
history.Execute(cmd2)
fmt.Println("After insert ' World':", editor.GetContent()) // Hello World
// 撤销一次
history.Undo()
fmt.Println("After undo:", editor.GetContent()) // Hello
// 撤销第二次
history.Undo()
fmt.Println("After second undo:", editor.GetContent()) // ""
// 删除部分内容再撤销
cmd3 := NewDeleteCommand(editor, 5)
history.Execute(cmd3)
fmt.Println("After delete 5 chars:", editor.GetContent()) // ""
history.Undo()
fmt.Println("After undo delete:", editor.GetContent()) // Hello}
通过命令模式,Golang可以优雅地实现撤销功能。关键点在于:
这种模式让新增操作变得容易,符合开闭原则,也提升了代码的可维护性。在实际项目中,还可扩展支持重做(Redo)、事务型命令、命令组合等功能。
基本上就这些。
以上就是Golang如何使用命令模式实现撤销功能_Golang Command模式撤销操作实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号