命令模式(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); } }