【C#设计模式(15)——命令模式(Command Pattern)】

前言

命令模式的关键通过将请求封装成一个对象,使命令的发送者和接收者解耦。这种方式能更方便地添加新的命令,如执行命令的排队、延迟、撤销和重做等操作。

代码

csharp 复制代码
#region 基础的命令模式
//命令(抽象类)
public abstract class Command
{
    public abstract void Execute();
}
//发送命令
public class SendCommand : Command
{
    private Receiver receiver;
    public SendCommand(Receiver receiver)
    {
        this.receiver = receiver;
    }
    public override void Execute()
    {
        receiver.Execute();
    }
}
//接收命令
public class Receiver
{
    public void Execute()
    {
        Console.WriteLine("receiver execute the command...");
    }
}
//调用者命令
public class Invoker
{
    private Command command;
    public void SetCommand(Command command)
    {
        this.command = command;
    }
    public void ExecuteCommand()
    {
        command.Execute();
    }
}
#endregion

#region 添加新的命令模式
//新命令
public class NewCommand : Command
{
    private NewReceiver newReceiver;
    public NewCommand(NewReceiver newReceiver)
    {
        this.newReceiver = newReceiver;
    }
    public override void Execute()
    {
        newReceiver.Execute();
    }
}
//使用新接收者
public class NewReceiver
{
    public void Execute()
    {
        Console.WriteLine("new reveiver execute the newCommand...");
    }
}

#endregion

#region 命令的请求的排队和延迟执行
//命令执行者
public class CommandInvoker
{
    private List<Command> commandQueue = new List<Command>();

    public void AddCommand(Command command)
    {
        commandQueue.Add(command);
    }
    public void ExecuteCommands()
    {
        foreach (Command command in commandQueue)
        {
            command.Execute();
        }
        commandQueue.Clear();
    }

    public void DelayExecute(Command command,int delay)
    {
        Console.WriteLine($"等待开始....时间:{delay}ms");
        new Thread(() =>
        {
            Console.WriteLine($"延时执行开始==>");
            Thread.Sleep(delay);
            command.Execute();
            Console.WriteLine($"finish time:{Environment.NewLine}{DateTime.Now.ToString("HH:mm:ss fff")}");
            Console.WriteLine($"==>延时执行完毕...");
        }).Start();
        
    }
}
#endregion

#region 命令撤销和重做操作
public interface ICommand
{
    void Execute();
    void Undo(); 
}

public class HistoryCommand : ICommand
{
    private HistoryReceiver historyReceiver;
    public HistoryCommand(HistoryReceiver historyReceiver)
    {
        this.historyReceiver = historyReceiver;
    }
    public void Execute()
    {
        historyReceiver.Execute();
    }
    public void Undo()
    {
        historyReceiver.UndoExecute();
    }
}

public class HistoryReceiver
{
    public void Execute()
    {
        Console.WriteLine("history receiver executes the command...");
    }
    public void UndoExecute()
    {
        Console.WriteLine("history receiver undoes the command...");
    }
}
public class HistoryInvoker
{
    private Stack<ICommand> commandStack = new Stack<ICommand>();

    public void ExecuteCommand(ICommand command)
    {
        command.Execute();
        commandStack.Push(command);
    }

    public void Undo()
    {
        if (commandStack.Count > 0)
        {
            ICommand command = commandStack.Pop();
            Console.WriteLine("command Undo");
            command.Undo();
        }
        else
        {

            Console.WriteLine("No commands to undo.");
        }
    }
    public void Redo()
    {
        if (commandStack.Count>0)
        {
            ICommand command = commandStack.Peek();
            Console.WriteLine("command Redo");
            command.Execute();
        }
        else
        {
            Console.WriteLine("No commands to redo.");
        }
    }
}


 /*
  * 行为型模式:Behavioral Pattern
  * 命令模型:Command Pattern
  */
 internal class Program
 {
     static void Main(string[] args)
     {
         //命令模式:简单实现
         Receiver receiver = new Receiver();
         Command sendCommand = new SendCommand(receiver);
         Invoker invoker = new Invoker();
         invoker.SetCommand(sendCommand);
         invoker.ExecuteCommand();

         Console.WriteLine("添加新命令------------------------------------");
         // 命令模式:添加新命令
         NewReceiver newReceiver = new NewReceiver();
         Command newCommand = new NewCommand(newReceiver);

         invoker.SetCommand(newCommand);
         invoker.ExecuteCommand();

         Console.WriteLine("请求队列------------------------------------");
         //命令模式:请求队列
         Receiver receiver1 = new Receiver();
         Command command1 = new SendCommand(receiver1);
         Command command2 = new SendCommand(receiver1);
         CommandInvoker commandInvoker = new CommandInvoker();
         commandInvoker.AddCommand(command1);
         commandInvoker.AddCommand(command2);
         commandInvoker.ExecuteCommands();

         Console.WriteLine("延时执行------------------------------------");
         Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss fff")}");
         //命令模式:延时执行
         commandInvoker.DelayExecute(command1,1000);

         Console.WriteLine("准备撤销重做------------------------------------");
         HistoryReceiver historyReceiver = new HistoryReceiver();
         ICommand command3 = new HistoryCommand(historyReceiver);
         ICommand command4 = new HistoryCommand(historyReceiver);

         HistoryInvoker historyInvoker = new HistoryInvoker();
         historyInvoker.ExecuteCommand(command3);
         historyInvoker.ExecuteCommand(command4);
         Console.WriteLine("执行撤销重做------------------------------------");
         //撤销最后一个命令
         historyInvoker.Undo();
         historyInvoker.Undo();
         //重做最后一个撤销命令
         historyInvoker.Redo();
         Console.WriteLine("END------------------------------------");
         Console.ReadLine();
     }
 }
#endregion

运行结果

相关推荐
吃一碗粉只付一碗钱7 小时前
16-SqlSugar多库ConfigId与按实体选连接
sqlserver·c#
rockey6278 小时前
AScript之字符串模板
c#·.net·script·expression·动态脚本
will_net9 小时前
Redis集群部署+Redis 链接地址放入Aollo +c#项目接入Redis
redis·c#·bootstrap
高晶10 小时前
SPMI 控制器 RTL 设计与验证新手入门
设计模式·程序员·架构
BuHuaX16 小时前
Lua 与 ToLua:运行机制及热更新原理
开发语言·unity·junit·c#·lua
asdzx6716 小时前
C# 操作 PDF 元数据:从属性写入到字段提取的完整流程
前端·pdf·c#
geovindu18 小时前
rust:N-Barrier Pattern
开发语言·后端·设计模式·rust·屏障模式·并发型模式
氷凌公子18 小时前
算法与UI拆分中遇到的问题及解决方式
c#·onnx·yolov26
顧棟18 小时前
OpenAPI 网关:鉴权 + 流量治理 一体化设计方案与实现
java·spring boot·设计模式