Skip to content

命令模式

将一个“操作请求”封装成一个对象,从而让你可以参数化调用者、排队执行命令、记录日志、撤销操作等等。

适用的场景

  • 需要将请求发出者与处理者解耦

  • 需要记录请求日志、实现操作撤销/重做

  • 需要把一组操作打包执行(组合命令)

  • 游戏开发中,角色操作、按钮控制、技能释放等

比如:

  • 点一下按钮就发出一个命令(遥控器逻辑!)

  • 撤销/重做系统

  • 命令队列(排队执行任务)

基本结构

plain text
[Invoker] ——> [Command] ——> [Receiver]
  • Invoker(请求发出者):发出命令(比如按钮)

  • Command(命令接口):定义执行方法

  • ConcreteCommand(具体命令):调用接收者逻辑

  • Receiver(命令的实际执行者):干活的那位

示例

csharp
// 命令接口
interface ICommand {
    void Execute();
}

// 命令接收者
class Light {
    public void TurnOn() => Console.WriteLine("Light is ON");
    public void TurnOff() => Console.WriteLine("Light is OFF");
}

// 具体命令
class LightOnCommand : ICommand {
    private Light _light;
    public LightOnCommand(Light light) => _light = light;
    public void Execute() => _light.TurnOn();
}

// 调用者(按钮)
class RemoteControl {
    private ICommand _command;
    public void SetCommand(ICommand command) => _command = command;
    public void PressButton() => _command.Execute();
}

// 使用
var light = new Light();
var onCommand = new LightOnCommand(light);
var remote = new RemoteControl();
remote.SetCommand(onCommand);
remote.PressButton(); // ➜ Light is ON

GDScript示例

gdscript
# 命令接口
class Command:
    func execute() -> void:
        pass

# 接收者
class Light:
    func turn_on():
        print("Light is ON")
    func turn_off():
        print("Light is OFF")

# 具体命令
class LightOnCommand extends Command:
    var light: Light
    func _init(light_ref: Light):
        light = light_ref
    func execute():
        light.turn_on()

# 调用者(按钮)
class Remote:
    var command: Command
    func set_command(c: Command):
        command = c
    func press():
        command.execute()

# 测试
func _ready():
    var light = Light.new()
    var command = LightOnCommand.new(light)
    var remote = Remote.new()
    remote.set_command(command)
    remote.press()  # ➜  Light is ON