烧烤店点餐示例:
实现1:
1.Receiver:
public class Barbecuer { public void BakeMutton() { Console.WriteLine("烤羊肉串!"); } public void BakeChickenWing() { Console.WriteLine("烤鸡翅!"); } }
2.Command:
public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) { this.receiver = receiver; } public abstract void ExcuteCommand(); }
3.ConcreteCommand:
public class BakeMuttonCommand:Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExcuteCommand() { receiver.BakeMutton(); } }
public class BakeChikenWingCommand:Command { public BakeChikenWingCommand(Barbecuer receiver) :base(receiver) { } public override void ExcuteCommand() { receiver.BakeChickenWing(); } }
4.Invoker:
public class Waiter { private Command command; public void SetOrder(Command command) { this.command = command; } public void Notify() { command.ExcuteCommand(); } }
5.客户端代码:
class Program { static void Main(string[] args) { Barbecuer barbecuer = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(barbecuer); Command bakeMuttonCommand2 = new BakeMuttonCommand(barbecuer); Command bakeChickenWingCommand1 = new BakeChikenWingCommand(barbecuer); Waiter waiter = new Waiter(); waiter.SetOrder(bakeMuttonCommand1); waiter.Notify(); waiter.SetOrder(bakeMuttonCommand2); waiter.Notify(); waiter.SetOrder(bakeChickenWingCommand1); waiter.Notify(); } }
实现2:增加命令队列、记录日志、否决请求、请求撤销
1.修改Invoker:
public class Waiter { private IList<Command> commands = new List<Command>();//命令队列 public void SetOrder(Command command) { if(command.ToString()=="Command.BakeChikenWingCommand") { Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。");//否决请求 } else { commands.Add(command); Console.WriteLine("增加订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString());//记录日志 } } public void Notify() { foreach(var command in commands) { command.ExcuteCommand(); } } }
2.修改客户端代码:
class Program { static void Main(string[] args) { Barbecuer barbecuer = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(barbecuer); Command bakeMuttonCommand2 = new BakeMuttonCommand(barbecuer); Command bakeChickenWingCommand1 = new BakeChikenWingCommand(barbecuer); Waiter waiter = new Waiter(); waiter.SetOrder(bakeMuttonCommand1); //waiter.Notify(); waiter.SetOrder(bakeMuttonCommand2); //waiter.Notify(); waiter.SetOrder(bakeChickenWingCommand1); waiter.Notify(); } }
命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开。优点:
1.较容易设计一个命令队列;
2.在需要的情况下,可以较容易地将命令记入日志;
3.允许接收请求的一方决定是否要否决请求;
4.较容易实现对请求的撤销和重做;
5.由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易。
敏捷开发的原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难。只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。