设计模式之命令模式
名词解释:
命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作.
必要元素:
1.用于执行操作的接口(抽象类);
2.一个或者多个实现(继承)自操作接口的类;
3.用于执行命令的类;
4.接收者,用于实施与请求相关的操作。
上例子:
命令接口:
abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } public abstract void Execute(); }
接口实现类:
class ConcreteCommand : Command { public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Action(); } }
执行请求类(接收者,也就是命令执行的操作就是该类的行为):
class Receiver { public void Action() { Console.WriteLine("执行请求!"); } }
执行命令类:
class Invoker { private Command command; public void SetCommand(Command command) { this.command = command; } public void ExecuteCommand() { command.Execute(); } }
调用:
Receiver r = new Receiver(); Command c = new ConcreteCommand(r); Invoker i = new Invoker(); i.SetCommand(c); i.ExecuteCommand(); Console.Read();
例子二(由于上述例子只是代码的构成部分,通过一个厨师做羊肉串和炸鸡翅,以及服务员向顾客询问点餐,这样一个场景):
抽象命令:
abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) { this.receiver=receiver; } public abstract void ExecuteCommand(); }
具体命令:
/// <summary> /// 烤鸡翅命令 /// </summary> class BakeChickenWingCommand:Command { public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeChickenWing(); } } /// <summary> /// 羊肉串命令 /// </summary> class BakeMuttonCommand:Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeMutton(); } }
厨师类(也就是执行请求类):
class Barbecuer { public void BakeMutton() { Console.WriteLine("烤羊肉串!"); } public void BakeChickenWing() { Console.WriteLine("烤鸡翅!"); } }
服务员类(执行命令):
class Waiter { private IList<Command> orders=new List<Command>(); public void SetCommand(Command command) { 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 (var command in orders) { command.ExecuteCommand(); } } }
调用:
Barbecuer boy = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); Command bakeMuttonCommand2 = new BakeMuttonCommand(boy); Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); Waiter girl = new Waiter(); girl.SetCommand(bakeMuttonCommand1); girl.SetCommand(bakeMuttonCommand2); girl.SetCommand(bakeChickenWingCommand1); girl.Notify(); Console.Read();
整个过程和我们的必要元素是一一对应的,在Command中依赖Receiver(也就是真正执行命令的),在Invoke(Waiter也就是服务员,可以进行命令的增加和移除,实现命令队列)中也是放入Command进行命令的执行。最终的调用过程也是一层层的进行设置,不管是Receiver的设置还是Command的增加移除。
总结:
命令模式的优点:较容易实现一个命令队列;容易将命令记入日志;容易实现对请求的撤销和重做;增加新命令也较容易。