设计模式(十九)命令模式
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
优点:
1、它能较容易地设计一个命令队列;
2、在需要的情况下,可以较容易地将命令记入日志;
3、允许接收请求的一方决定是否要否决请求;
4、可以容易地实现对请求的撤销和重做;
5、由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;
6、命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。
敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际上不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。

基本代码
1 // Command 类,用来声明执行操作的接口 2 abstract class Command 3 { 4 protected Receiver receiver; 5 6 public Command(Receiver receiver) 7 { 8 this.receiver = receiver; 9 } 10 11 abstract public void Execute(); 12 } 13 14 // ConcreteCommand 类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现 Execute 15 class ConcreteCommand : Command 16 { 17 public ConcreteCommand(Receiver receiver) : base(receiver) 18 { 19 } 20 21 public override void Execute() 22 { 23 receiver.Action(); 24 } 25 } 26 27 // Invoker 类,要求该命令执行这个请求 28 class Invoker 29 { 30 private Command command; 31 32 public void SetCommand(Command command) 33 { 34 this.command = command; 35 } 36 37 public void ExecuteCommand() 38 { 39 command.Execute(); 40 } 41 } 42 43 // Receiver 类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者 44 class Receiver 45 { 46 public void Action() 47 { 48 Console.WriteLine("执行请求!"); 49 } 50 } 51 52 // 客户端 53 static void Main(string[] args) 54 { 55 Receiver r = new Receiver(); 56 Command c = new ConcreteCommand(); 57 58 Invoker i = new Invoker(); 59 i.SetCommand(c); 60 i.ExecuteCommand(); 61 62 Console.Read(); 63 }
【例】吃烧烤

基本代码
1 // 烤肉串者 2 public clas Barbecuer 3 { 4 // 烤羊肉 5 public void BakeMutton() 6 { 7 Console.WriteLine("烤羊肉串"); 8 } 9 // 烤鸡翅 10 public void BakeChickenWing() 11 { 12 Console.WriteLine("烤鸡翅"); 13 } 14 } 15 16 // 抽象命令类,只需要确定 “烤肉串者” 是谁 17 public abstract class Command 18 { 19 protected Barbecuer receiver; 20 21 public Command(Barbecuer receiver) 22 { 23 this.receiver = receiver; 24 } 25 // 执行命令 26 abstract public void ExecuteCommand(); 27 } 28 29 // 具体命令类,执行命令时,执行具体的行为 30 // 烤羊肉串命令 31 class BakeMuttonCommand : Command 32 { 33 public BakeMuttonCommand(Barbecuer receiver) : base(receiver) 34 { 35 } 36 37 public override void ExecuteCommand() 38 { 39 receiver.BakeMutton(); 40 } 41 } 42 43 // 烤鸡翅命令 44 class BakeChickenWingCommand : Command 45 { 46 public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) 47 { 48 } 49 50 public override void ExecuteCommand() 51 { 52 receiver.BakeChickenWing(); 53 } 54 } 55 56 // 服务员类,不用管用户想要什么烤肉,反之都是 “命令”,只管记录订单,然后通知 “烤肉串者 ” 执行即可 57 public class Waiter 58 { 59 // 增加存放具体命令的容器 60 private IList<Command>orders = new List<Command>(); 61 62 // 设置订单 63 public void SetOrder(Command command) 64 { 65 if(command.ToString() == "命令模式.BakeChickenWingCommand") 66 { 67 Console.WriteLine("服务员:鸡翅没了。"); 68 }else 69 { 70 orders.Add(command); 71 // 记录日志 72 Console.WriteLine("增加订单:" + command.ToString() + "时间:" + DateTime.Now.ToString()); 73 } 74 } 75 76 // 取消订单 77 public void CancelOrder(Command command) 78 { 79 orders.Remove(command); 80 // 记录日志 81 Console.WriteLine("取消订单:" + command.ToString() + "时间:" + DateTime.Now.ToString()); 82 } 83 84 // 通知执行(通知厨房制作) 85 public void Notify() 86 { 87 foreach(Command cmd in orders) 88 { 89 cmd.ExecuteCommand(); 90 } 91 } 92 } 93 94 // 客户端 95 static void Main(string[] args) 96 { 97 // 开店前的准备(烤肉厨师、服务员、烤肉菜单) 98 Barbecuer boy = new Barbecuer(); 99 Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); 100 Command bakeMuttonCommand2 = new BakeMuttonCommand(boy); 101 Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); 102 Waiter girl = new Waiter(); 103 104 // 开门营业(顾客点菜) 105 girl.SetOrder(bakeMuttonCommand1); 106 girl.SetOrder(bakeMuttonCommand2); 107 girl.SetOrder(bakeChickenWingCommand1); 108 109 // 通知厨房(订单下好后,一次通知) 110 girl.Notify(); 111 112 Console.Read(); 113 }

浙公网安备 33010602011771号