通八洲科技

如何使用Golang实现命令模式_使用Command Pattern封装操作请求

日期:2025-12-21 00:00 / 作者:P粉602998670
Go中命令模式用函数类型和结构体组合实现松耦合,将请求变为可存储、传递、延迟执行的一等公民:定义Command函数类型或含execute/undo字段的结构体,用闭包或结构体封装具体行为,Invoker统一调度,接收者通过闭包捕获或字段引用解耦。

命令模式在 Go 中不依赖接口继承,而是通过函数类型和结构体组合实现松耦合——核心是把“请求”变成可存储、可传递、可延迟执行的一等公民。

定义命令接口:用函数类型替代传统 interface

Go 偏好简洁,直接用函数类型 func() 表达无参无返回的命令,比定义空 interface 更轻量:

type Command func()

若需参数或返回值,可封装为闭包或使用带字段的结构体。例如支持撤销的命令可定义为:

type Command struct {
  execute func()
  undo func()
}

实现具体命令:闭包或结构体都行

对某个操作(如打开文件、发送邮件)封装成命令实例,关键是把行为和上下文绑定:

构建调用者(Invoker):统一调度,不关心具体逻辑

调用者持有命令并触发执行,也可管理历史、支持撤销/重做:

type Invoker struct {
  history []Command
}

func (i *Invoker) Execute(cmd Command) {
  i.history = append(i.history, cmd)
  cmd()
}

func (i *Invoker) Undo() {
  if len(i.history) > 0 {
    last := i.history[len(i.history)-1]
    i.history = i.history[:len(i.history)-1]
    // 实际中 undo 需单独设计,此处仅示意
  }
}

连接接收者与命令:解耦关键一步

接收者(Receiver)是真正干活的对象(如 FileSaverNotifier)。命令内部持有接收者引用或通过闭包捕获,确保执行时能调用其方法:

这样调用者只认 Command 类型,完全不知道背后是发邮件还是写日志。

基本上就这些——Go 的命令模式不靠抽象层级堆砌,而靠函数即值、闭包捕获、结构体组合来自然表达意图。重点不是“像不像经典 UML”,而是让请求可序列化、可审计、可回滚、可排队。