命令模式

命令模式的概念

命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而允许用户使用不同的请求、队列或日志来参数化对象。命令模式还支持可撤销的操作。

相关概念

Command(抽象命令):定义了执行操作的接口。

ConcreteCommand(具体命令):实现抽象命令接口,绑定一个接收者对象,并调用其方法。

Receiver(接收者):执行与命令相关的业务逻辑。

Invoker(调用者):负责调用命令对象的执行方法。

Client(客户端):创建具体命令对象,并设置其接收者。

命令模式的作用

解耦:将请求的发送者和接收者解耦,使两者不直接依赖。

扩展性:可以很容易地添加新的命令类,而无需修改现有代码。

支持撤销操作:通过保存命令对象的状态,可以实现撤销和重做功能。

队列请求:可以将多个命令放入队列中,按顺序执行。

命令模式的应用场景

GUI 应用程序:如按钮点击事件、菜单项选择等。

事务处理:需要支持撤销和重做的操作。

宏命令:将多个命令组合成一个命令。

远程调用:将请求封装为命令对象,通过网络传递到远程服务器执行。

Go 语言实现命令模式的例子

以下是一个简单的例子,展示如何使用命令模式控制家用电器(如灯和电视)的开关。

package main

import "fmt"

// 接收者:家用电器
type Device interface {
	TurnOn()
	TurnOff()
}

// 具体接收者:灯
type Light struct{}
func (l *Light) TurnOn() {
	fmt.Println("Light is ON")
}
func (l *Light) TurnOff() {
	fmt.Println("Light is OFF")
}

// 具体接收者:电视
type TV struct{}
func (t *TV) TurnOn() {
	fmt.Println("TV is ON")
}
func (t *TV) TurnOff() {
	fmt.Println("TV is OFF")
}

// 抽象命令
type Command interface {
	Execute()
	Undo()
}
// 具体命令:打开设备
type OnCommand struct {
	device Device
}
func (oc *OnCommand) Execute() {
	oc.device.TurnOn()
}
func (oc *OnCommand) Undo() {
	oc.device.TurnOff()
}
// 具体命令:关闭设备
type OffCommand struct {
	device Device
}
func (ofc *OffCommand) Execute() {
	ofc.device.TurnOff()
}
func (ofc *OffCommand) Undo() {
	ofc.device.TurnOn()
}

// 调用者:遥控器
type RemoteControl struct {
	onCommand  Command
	offCommand Command
}
func (rc *RemoteControl) SetCommand(onCommand, offCommand Command) {
	rc.onCommand = onCommand
	rc.offCommand = offCommand
}
func (rc *RemoteControl) PressOnButton() {
	rc.onCommand.Execute()
}
func (rc *RemoteControl) PressOffButton() {
	rc.offCommand.Execute()
}
func (rc *RemoteControl) PressUndoButton() {
	if rc.onCommand != nil {
		rc.onCommand.Undo()
	} else if rc.offCommand != nil {
		rc.offCommand.Undo()
	}
}

func main() {
	// 创建接收者
	light := &Light{}
	tv := &TV{}

	// 创建命令
	lightOn := &OnCommand{device: light}
	lightOff := &OffCommand{device: light}

	tvOn := &OnCommand{device: tv}
	tvOff := &OffCommand{device: tv}

	// 创建调用者
	remote := &RemoteControl{}

	// 设置灯的命令
	remote.SetCommand(lightOn, lightOff)
	fmt.Println("Pressing Light Buttons:")
	remote.PressOnButton()
	remote.PressOffButton()
	remote.PressUndoButton()

	fmt.Println("\nPressing TV Buttons:")
	// 设置电视的命令
	remote.SetCommand(tvOn, tvOff)
	remote.PressOnButton()
	remote.PressOffButton()
	remote.PressUndoButton()
}