命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。
下面给出命令模式的结构图:
下面是命令模式的基本结构代码:
namespace ConsoleApplication1 { abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } abstract public void Execute(); } //ConcreteCommand类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute class ConcreteCommand : Command { public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Action(); } } //Invoker类,要求该命令执行这个请求 class Invoker { private Command command; public void SetCommand(Command command) { this.command = command; } public void ExecuteCommand() { command.Execute(); } } //Receiver类,知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者 class Receiver { public void Action() { Console.WriteLine("执行请求!"); } } class Program { static void Main(string[] args) { Receiver r = new Receiver(); Command c = new ConcreteCommand(r); Invoker i = new Invoker(); i.SetCommand(c); i.ExecuteCommand(); Console.ReadKey(); } } }
命令模式的优点:
1、它能较容易地设计一个命令队列;
2、在需要的情况下,可以叫容易地将命令计入日志;
3、允许接收请求的一方决定是否要否决请求。
4、可以容易地实现对请求的撤销和重做;
5、由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
6、最关键的一点,命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
回到《大话设计模式》书中的烧烤例子:
namespace ConsoleApplication1 { public class Barbecuer { //烤羊肉 public void BakeMutton() { Console.WriteLine("烤羊肉串"); } //烤鸡翅 public void BakeChickenWing() { Console.WriteLine("烤鸡翅"); } } //抽象命令 public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) //抽象命令类,只需要确定‘烤羊肉串者’是谁 { this.receiver = receiver; } //执行命令 abstract public void ExecuteCommand(); } //烤羊肉串命令 class BakeMuttonCommand : Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeMutton(); } } //烤鸡翅命令 class BakeChickenWingCommand : Command { public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeChickenWing(); } } //服务员类 public class Waiter { private IList<Command> orders = new List<Command>(); //增加存放具体命令的容器 //设置订单 public void SetOrder(Command command) //在客户提出请求时,对没货的烧烤进行回绝 { if (command.ToString() == "命令模式.BakeChickenWingCommand") { Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤"); } else { orders.Add(command); Console.WriteLine("增加订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString()); } } //取消订单 public void CancelOrder(Command command) //记录客户所点的烧烤的日志,以便算账收钱 { orders.Remove(command); Console.WriteLine("取消订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString()); } //通知全部执行 public void Notify() { foreach (Command cmd in orders) { cmd.ExecuteCommand(); } } } class Program { static void Main(string[] args) { //开店前的准备 Barbecuer boy = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); Command bakeMuttonCommand2 = new BakeMuttonCommand(boy); Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); Waiter girl = new Waiter(); //开门营业 girl.SetOrder(bakeMuttonCommand1); girl.SetOrder(bakeMuttonCommand2); girl.SetOrder(bakeChickenWingCommand1); //点菜完毕,通知厨房 girl.Notify(); //订单下好后,一次性通知 在通知之前都可以取消 Console.ReadKey(); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现