跳到主要内容

命令模式

简介

命令模式(Command Pattern)是一种行为型设计模式,它将请求或操作封装为独立的对象,允许用户参数化客户端、队列请求、记录日志,并支持撤销操作。该模式的核心思想是将“请求的发起者”与“请求的执行者”解耦,使两者通过命令对象进行交互。

角色组成:

  • 调用者(Invoker),负责发起请求的类
  • 命令(Command),一个接口,通常仅声明一个执行命令的方法
  • 具体命令(ConcretCommand),实现各种类型请求的类
  • 接受者(Receiver),包含部分业务逻辑的接口或类。大部分命令只处理如何将请求传递给接受者的细节,接受者会完成实际的工作。
  • 客户端(Client),创建并配置具体命令对象。

适用场景

  1. 解耦请求发起者与执行者:当需要将操作调用者(如UI控件)与具体实现(如业务逻辑)分离时。
  2. 支持撤销/重做:如文本编辑器、图形软件中的操作历史。
  3. 延迟执行或任务队列:将命令存入队列,按计划或异步执行。
  4. 事务管理:将多个操作组合成原子事务,支持回滚。
  5. 宏命令(组合命令):批量执行一系列命令。

优点

  1. 解耦:调用者与接收者无需直接交互,降低耦合度。
  2. 扩展性:新增命令无需修改现有代码,符合开闭原则。
  3. 支持复杂操作:可轻松实现撤销、重做、事务、宏命令。
  4. 灵活调度:命令可排队、延迟执行或记录日志。

缺点

  1. 类数量增加:每个命令需单独类,可能导致代码膨胀。
  2. 复杂度提升:对简单操作可能过度设计,增加理解成本。
  3. 性能开销:多层间接调用可能影响效率(通常可忽略)。

示例代码

command.go
package command

import "fmt"

// 命令 接口
type Command interface {
Execute()
}

// 调用者类
type Button struct {
Command Command
}

func (b *Button) Press() {
b.Command.Execute()
}

// 具体命令类
type OnCommand struct {
Device Device
}

func (c *OnCommand) Execute() {
c.Device.On()
}

// 具体命令类
type OffCommand struct {
Device Device
}

func (c *OffCommand) Execute() {
c.Device.Off()
}

// 接收者接口
type Device interface {
On()
Off()
}

// 具体接受者类
type Light struct {
isRunning bool
}

func (t *Light) On() {
t.isRunning = true
fmt.Println("Light is on")
}

func (t *Light) Off() {
t.isRunning = false
fmt.Println("Light is off")
}

客户端

command_test.go
package command

import "testing"

func TestCommand(t *testing.T) {
Light := &Light{}

onCommand := &OnCommand{
Device: Light,
}

OffCommand := &OffCommand{
Device: Light,
}

onButton := &Button{
Command: onCommand,
}

onButton.Press()

offButton := &Button{
Command: OffCommand,
}
offButton.Press()
}