如何使用Golang实现命令模式_封装请求和执行操作

11次阅读

命令模式的核心是将请求封装对象以解耦发送者与执行者;go中通过接口结构体组合实现,支持Execute/Undo方法、调用者调度及闭包简化命令。

如何使用Golang实现命令模式_封装请求和执行操作

命令模式的核心是把请求封装成对象,使发出请求的对象与执行请求的对象解耦。在 Go 中没有接口继承和类的概念,但通过接口(Interface{})和结构体组合,可以简洁、自然地实现命令模式。

定义命令接口和具体命令

先定义一个通用的 Command 接口,要求所有命令都实现 Execute() 方法:

type Command interface {     Execute() }

然后为不同操作创建具体命令结构体。例如,实现一个开关灯的命令:

type Light struct {     isOn bool } 

func (l Light) TurnOn() { l.isOn = true; fmt.Println("灯已打开") } func (l Light) TurnOff() { l.isOn = false; fmt.Println("灯已关闭") }

type LightOnCommand struct { light *Light }

func (c *LightOnCommand) Execute() { c.light.TurnOn() }

type LightOffCommand struct { light *Light }

func (c *LightOffCommand) Execute() { c.light.TurnOff() }

引入调用者(Invoker)统一调度

调用者不关心命令具体做什么,只负责持有并执行命令。它通常提供设置命令和触发执行的方法:

立即学习go语言免费学习笔记(深入)”;

type RemoteControl struct {     command Command } 

func (r *RemoteControl) SetCommand(cmd Command) { r.command = cmd }

func (r *RemoteControl) PressButton() { if r.command != nil { r.command.Execute() } }

使用方式很直观:

light := &Light{} onCmd := &LightOnCommand{light: light} offCmd := &LightOffCommand{light: light} 

remote := &RemoteControl{}

remote.SetCommand(onCmd) remote.PressButton() // 输出:灯已打开

remote.SetCommand(offCmd) remote.PressButton() // 输出:灯已关闭

支持撤销操作(可选增强)

若需支持撤销,可在命令接口中增加 Undo() 方法,并让具体命令保存执行前的状态:

type Command interface {     Execute()     Undo() } 

func (c *LightOnCommand) Undo() { c.light.TurnOff() }

func (c *LightOffCommand) Undo() { c.light.TurnOn() }

调用者也可扩展支持撤销:

type RemoteControl struct {     command Command     history []Command // 简单记录最近执行的命令,用于撤销 } 

func (r *RemoteControl) PressButton() { if r.command != nil { r.command.Execute() r.history = append(r.history, r.command) } }

func (r *RemoteControl) UndoLast() { if len(r.history) > 0 { last := r.history[len(r.history)-1] last.Undo() r.history = r.history[:len(r.history)-1] } }

利用闭包简化简单命令(轻量替代方案)

对于逻辑简单的操作,不必定义完整结构体,可用闭包快速构造命令:

type FuncCommand func() 

func (f FuncCommand) Execute() { f() } func (f FuncCommand) Undo() { / 可按需实现 / }

// 使用示例 cmd := FuncCommand(func() { fmt.Println("执行自定义操作") }) var invoker RemoteControl invoker.SetCommand(cmd) invoker.PressButton()

这种方式灵活、无侵入,适合脚本化或配置驱动的场景。

text=ZqhQzanResources