命令模式

定义

命令模式(Command Pattern)是一种行为设计模式,它将请求封装为独立的对象,从而允许用户参数化其他对象,并支持请求的排队、记录、撤销/重做等操作。该模式通过解耦请求的发送者和接收者,提高了系统的灵活性和可扩展性。

​核心思想​​

  • ​​将请求封装成对象​​:将每个操作(如“打开文件”“保存数据”)抽象为命令对象,包含执行操作所需的所有信息。
  • ​​解耦调用者与接收者​​:调用者(如按钮、菜单)无需知道具体操作如何执行,只需触发命令对象;接收者(如文档、设备)负责实际执行操作。

​​模式结构​​

命令模式包含以下角色:

  1. ​​命令接口(Command)​​
    定义执行操作的抽象方法(如 execute()),通常包含撤销方法(如 undo())。

  2. ​​具体命令(Concrete Command)​​

    • 实现命令接口,关联一个接收者(Receiver)。
    • 在 execute() 中调用接收者的具体方法(如 receiver.action())。
  3. ​​接收者(Receiver)​​
    真正执行操作的对象(如“灯”执行“打开”或“关闭”)。

  4. ​​调用者(Invoker)​​
    触发命令的对象(如按钮、遥控器),持有命令对象并调用其 execute()

  5. ​​客户端(Client)​​
    创建具体命令对象,并设置其接收者和调用者。


​​工作流程​​

  1. ​​客户端创建命令对象​​,并关联接收者。
  2. ​​调用者持有命令对象​​,并在适当时机(如按钮点击)调用 execute()
  3. ​​具体命令调用接收者的方法​​,完成实际操作。
  4. (可选)命令记录状态以支持撤销/重做。

​​代码示例​​

以“遥控器控制灯”为例:

using System;

// 1. 命令接口(定义执行和撤销操作)
public interface ICommand
{
    void Execute();
    void Undo();
}
// 2. 接收者:电灯(实际执行操作的对象)
public class Light
{
    public void TurnOn() => Console.WriteLine( "电灯已打开" );
    public void TurnOff() => Console.WriteLine( "电灯已关闭" );
}
// 3. 具体命令:开灯命令
public class TurnOnCommand : ICommand
{
    private Light _light;
    public TurnOnCommand(Light light)
    {
        _light = light;
    }
    public void Execute() => _light.TurnOn();
    public void Undo() => _light.TurnOff();
}
// 4. 具体命令:关灯命令
public class TurnOffCommand : ICommand
{
    private Light _light;
    public TurnOffCommand(Light light)
    {
        _light = light;
    }
    public void Execute() => _light.TurnOff();
    public void Undo() => _light.TurnOn();
}
// 5. 调用者:遥控器(触发命令的对象)
public class RemoteControl
{
    private ICommand _command;
    // 设置命令
    public void SetCommand(ICommand command)
    {
        _command = command;
    }
    // 执行命令
    public void PressButton()
    {
        _command.Execute();
    }
    // 撤销命令
    public void PressUndo()
    {
        _command.Undo();
    }
}
// 6. 客户端代码
class Program
{
    static void Main()
    {
        // 创建接收者(电灯)
        Light light =  new Light();
// 创建具体命令并关联接收者 ICommand turnOn = new TurnOnCommand(light); ICommand turnOff = new TurnOffCommand(light);
// 创建调用者(遥控器) RemoteControl remote = new RemoteControl();
// 执行开灯命令 remote.SetCommand(turnOn); remote.PressButton();  // 输出:电灯已打开 remote.PressUndo();    // 输出:电灯已关闭 // 执行关灯命令 remote.SetCommand(turnOff); remote.PressButton();  // 输出:电灯已关闭 remote.PressUndo();    // 输出:电灯已打开 } }

 

代码说明​​

    1. ​​命令接口 ICommand​​
      定义 Execute() 和 Undo() 方法,所有具体命令必须实现这两个操作。

    2. ​​接收者 Light​​
      实际执行操作的对象,提供 TurnOn() 和 TurnOff() 方法。

    3. ​​具体命令 TurnOnCommand/TurnOffCommand​​

      • 关联接收者 Light,并在 Execute() 中调用其方法。
      • Undo() 实现反向操作(如开灯的撤销是关灯)。
    4. ​​调用者 RemoteControl​​

      • 持有命令对象,通过 PressButton() 触发命令执行。
      • 通过 PressUndo() 触发撤销操作。
    5. ​​客户端 Program​​

      • 组合接收者、命令和调用者。
      • 演示命令的链式调用(执行与撤销)。

  ​

 

 


​扩展场景:宏命令(批量操作)​

// 定义宏命令(组合多个命令)
public class MacroCommand : ICommand
{
 List _commands =  new List();

    public void AddCommand(ICommand command)
    {
        _commands.Add(command);
    }

    public void Execute()
    {
        foreach ( var cmd  in _commands)
        {
            cmd.Execute();
        }
    }

    public void Undo()
    {
        // 反向撤销所有命令
        foreach ( var cmd  in _commands.AsEnumerable().Reverse())
        {
            cmd.Undo();
        }
    }
}

// 客户端使用宏命令
static void Main()
{
    Light light =  new Light();
    ICommand turnOn =  new TurnOnCommand(light);
    ICommand turnOff =  new TurnOffCommand(light);

    // 创建宏命令(开灯 -> 关灯 -> 开灯)
    MacroCommand macro =  new MacroCommand();
    macro.AddCommand(turnOn);
    macro.AddCommand(turnOff);
    macro.AddCommand(turnOn);

    RemoteControl remote =  new RemoteControl();
    remote.SetCommand(macro);

    Console.WriteLine( "执行宏命令:" );
    remote.PressButton();
    // 输出:
    // 电灯已打开
    // 电灯已关闭
    // 电灯已打开

    Console.WriteLine( "撤销宏命令:" );
    remote.PressUndo();
    // 输出:
    // 电灯已关闭
    // 电灯已打开
    // 电灯已关闭
}

  

应用场景总结​

  • ​GUI 按钮/菜单​​:将点击事件绑定到命令对象。
  • ​事务管理​​:记录操作历史以实现撤销/重做。
  • ​任务队列​​:将命令存入队列异步执行。
  • ​批处理操作​​:通过宏命令组合多个操作。

命令模式在 C# 中广泛应用于 WPF 的 ICommand 接口(如 RelayCommand)、ASP.NET Core 中间件等场景,是解耦请求与处理的经典设计模式。

 
posted @ 2025-04-11 16:05  刘继先  阅读(36)  评论(0)    收藏  举报