命令模式(Command)(行动(Action)模式或交易(Transaction)模式。),是一种数据驱动的设计模式,它属于行为型模式,将一个请求封装成一个对象,从而使你可用不一样的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操做。c#
命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不一样的对象。设计模式
命令容许请求的一方和接收请求的一方可以独立演化,从而有如下的优势:ide
命令模式使新的命令很容易地被加入到系统里。
容许接收请求的一方决定是否要否决(Veto)请求。
能较容易地设计一个命令队列。
能够容易地实现对请求的Undo和Redo。
在须要的状况下,能够较容易地将命令记入日志。
命令模式把请求一个操做的对象与知道怎么执行一个操做的对象分割开。
命令类与其余任何别的类同样,能够修改和推广。this
缺点:使用命令模式可能会致使某些系统有过多的具体命令类。设计
命令模式UML结构图:日志
例(烤羊肉串):code
UML图:对象
代码实现:队列
//服务员 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.ExcuteCommand(); } } } //抽象命令 public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) { this.receiver = receiver; } //执行命令 abstract public void ExcuteCommand(); } //烤羊肉串命令 class BakeMuttonCommand : Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExcuteCommand() { receiver.BakeMutton(); } } //烤鸡翅命令 class BakeChickenWingCommand : Command { public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) { } public override void ExcuteCommand() { receiver.BakeChickenWing(); } } //烤肉串者 public class Barbecuer { public void BakeMutton() { Console.WriteLine("烤羊肉串!"); } public void BakeChickenWing() { Console.WriteLine("烤鸡翅!"); } } 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.Read(); } }
例(计算器——容许执行undo与redo):cmd
UML图:
代码实现:
abstract class Command { // Methods abstract public void Execute(); abstract public void UnExecute(); } class CalculatorCommand : Command { char @operator; //"operator"在C#中是关键词,因此在前面添加一个"@"将其变为标识符 int operand; Calculator calculator; public CalculatorCommand(Calculator calculator, char @operator, int operand) { this.calculator = calculator; this.@operator = @operator; this.operand = operand; } public char Operator { set { @operator = value; } } public int Operand { set { operand = value; } } override public void Execute() { calculator.Operation(@operator, operand); } override public void UnExecute() { calculator.Operation(Undo(@operator), operand); } private char Undo(char @operator) { char undo = ' '; switch (@operator) { case '+': undo = '-'; break; case '-': undo = '+'; break; case '*': undo = '/'; break; case '/': undo = '*'; break; } return undo; } } class Calculator { private int total = 0; public void Operation(char @operator, int operand) { switch (@operator) { case '+': total += operand; break; case '-': total -= operand; break; case '*': total *= operand; break; case '/': total /= operand; break; } Console.WriteLine("Total = {0} (following {1} {2})", total, @operator, operand); } } class User { private Calculator calculator = new Calculator(); private ArrayList commands = new ArrayList(); private int current = 0; public void Redo(int levels) { Console.WriteLine("---- Redo {0} levels ", levels); for (int i = 0; i < levels; i++) if (current < commands.Count - 1) ((Command)commands[current++]).Execute(); } public void Undo(int levels) { Console.WriteLine("---- Undo {0} levels ", levels); for (int i = 0; i < levels; i++) if (current > 0) ((Command)commands[--current]).UnExecute(); } public void Compute(char @operator, int operand) { Command command = new CalculatorCommand( calculator, @operator, operand); command.Execute(); commands.Add(command); current++; } } public class Client { static void Main(string[] args) { User user = new User(); user.Compute('+', 100); user.Compute('-', 50); user.Compute('*', 10); user.Compute('/', 2); user.Undo(4); user.Redo(3); } }