命令模式(Command):
將請求封裝成物件,以便使用不同的請求、日志、佇列等來引數化其他物件,命令模式也支持撤銷操作,
命令模式的角色:

1)傳遞命令物件(Invoker):是請求的發送者,它通常擁有很多的命令物件,并通過訪問命令物件來執行相關請求,它不直接訪問接收者,
2)抽象命令介面(Command):宣告執行命令的介面,擁有執行命令的抽象方法execute(),
3)具體的命令物件(ConcreteCommand):是抽象命令類的具體實作類,它擁有接收者物件,并通過呼叫接收者的功能來完成命令要執行的操作,
4)接受者物件(Receiver):執行命令功能的相關操作,是具體命令物件業務的真正實作者,
5)客戶端物件(Client):創建具體命令的物件并且設定命令物件的接受者,
示例:
土豪小明是一個狂熱的科技迷,因此將家中電器進行了全面升級,更換成了智能家電,通過小愛同學可以統一控制,只需要一句"小愛同學,打開電燈"...,那么我們的故事就從這里開始,

1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 // 創建電燈的物件 6 LightReceiver lightReceiver = new LightReceiver(); 7 // 創建電燈的開關命令 8 Command lightOnCommand = new LightOnCommand(lightReceiver); 9 Command lightOffCommand = new LightOffCommand(lightReceiver); 10 // 創建遙控器-小愛同學 11 RemoteController remoteController = new RemoteController(); 12 // 設定 13 remoteController.setCommand(0, lightOnCommand, lightOffCommand); 14 // 執行命令 15 remoteController.onExecute(0); 16 remoteController.Undo(); 17 } 18 } 19 20 /// <summary> 21 /// 抽象命令介面 22 /// </summary> 23 public interface Command 24 { 25 /// <summary> 26 /// 執行 27 /// </summary> 28 void execute(); 29 30 /// <summary> 31 /// 撤銷 32 /// </summary> 33 void undo(); 34 } 35 36 /// <summary> 37 /// 接受者物件 38 /// </summary> 39 public class LightReceiver 40 { 41 public void on() 42 { 43 Console.WriteLine("電燈打開了..."); 44 } 45 46 public void off() 47 { 48 Console.WriteLine("電燈關閉了..."); 49 } 50 } 51 52 /// <summary> 53 /// 具體的命令物件 54 /// </summary> 55 internal class LightOnCommand : Command 56 { 57 private readonly LightReceiver lightReceiver; 58 59 public LightOnCommand(LightReceiver lightReceiver) 60 { 61 this.lightReceiver = lightReceiver; 62 } 63 64 public void execute() 65 { 66 // 呼叫接收者的方法 67 lightReceiver.on(); 68 } 69 70 public void undo() 71 { 72 // 呼叫接收者的方法 73 lightReceiver.off(); 74 } 75 } 76 77 /// <summary> 78 /// 具體的命令物件 79 /// </summary> 80 internal class LightOffCommand : Command 81 { 82 private readonly LightReceiver lightReceiver; 83 84 public LightOffCommand(LightReceiver lightReceiver) 85 { 86 this.lightReceiver = lightReceiver; 87 } 88 89 public void execute() 90 { 91 // 呼叫接收者的方法 92 lightReceiver.off(); 93 } 94 95 public void undo() 96 { 97 // 呼叫接收者的方法 98 lightReceiver.on(); 99 }100 }101 102 /// <summary>103 /// 空命令,用于初始化104 /// </summary>105 internal class NoCommand : Command106 {107 public void execute()108 {109 }110 111 public void undo()112 {113 }114 }115 116 internal class RemoteController117 {118 // 按鈕的命令陣列119 private Command[] onCommands;120 121 private Command[] offCommands;122 123 // 撤銷命令124 private Command undoCommand;125 126 public RemoteController()127 {128 // 假設小愛同學需要連接5款智能家電129 onCommands = new Command[5];130 offCommands = new Command[5];131 for (int i = 0; i < 5; i++)132 {133 onCommands[i] = new NoCommand();134 offCommands[i] = new NoCommand();135 }136 }137 138 // 給小愛同學設定需要的命令139 public void setCommand(int no, Command onCommand, Command offCommand)140 {141 onCommands[no] = onCommand;142 offCommands[no] = offCommand;143 }144 145 // 對小愛同學下達打開命令146 public void onExecute(int no)147 {148 // 小愛同學執行打開操作149 onCommands[no].execute();150 // 記錄操作,用于撤回151 undoCommand = onCommands[no];152 }153 154 // 對小愛同學下達關閉命令155 public void offExecute(int no)156 {157 // 小愛同學執行關閉操作158 offCommands[no].execute();159 // 記錄操作,用于撤回160 undoCommand = offCommands[no];161 }162 163 /// <summary>164 /// 撤銷上次操作165 /// </summary>166 public void Undo()167 {168 undoCommand.undo();169 }170 }
命令模式的優缺點:
優點:
1)降低系統的耦合度,命令模式能將呼叫操作的物件與實作該操作的物件解耦,
2)增加或洗掉命令非常方便,采用命令模式增加與洗掉命令不會影響其他類,它滿足OCP原則,對擴展比較靈活,
3)可以實作宏命令,命令模式可以與組合模式結合,將多個命令裝配成一個組合命令,即宏命令,
4)方便實作 Undo 和 Redo 操作,命令模式可以與備忘錄模式結合,實作命令的撤銷與恢復,
缺點:可能產生大量的具體命令類,
適用環境:
1)使用命令模式作為“CallBack”在面向物件系統中的替代,“CallBack”講的便是先將一個函式登記上,然后在以后呼叫此函式,
2)需要在不同的時間指定請求、將請求排隊,一個命令物件和原先的請求發出者可以有不同的生命期,換言之,原先的請求發出者可能已經不在了,而命令物件本身仍然是活動的,這時命令的接收者可以是在本地,也可以在網路的另外一個地址,命令物件可以在串形化之后傳送到另外一臺機器上去,
3)系統需要支持命令的撤消(undo),命令物件可以把狀態存盤起來,等到客戶端需要撤銷命令所產生的效果時,可以呼叫undo()方法,把命令所產生的效果撤銷掉,命令物件還可以提供redo()方法,以供客戶端在需要時,再重新實施命令效果,
4)如果一個系統要將系統中所有的資料更新到日志里,以便在系統崩潰時,可以根據日志里讀回所有的資料更新命令,重新呼叫Execute()方法一條一條執行這些命令,從而恢復系統在崩潰前所做的資料更新,
命令模式與策略模式的區別:
1)命令模式與策略模式都封裝了變化,但命令模式封裝的是請求的變化,而策略模式封裝的是演算法的變化,
2)命令模式可以抽象化成策略模式,策略模式較簡單,而命令模式比較復雜,策略模式聚焦的是對相同請求更換解決方案的靈活性;而命令模式聚焦的是對多請求變化的封裝以及對相同請求不同的請求形式解決方法的可復用性,
參考:https://blog.csdn.net/zhwyj1019/article/details/79758057
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/42114.html
標籤:設計模式
上一篇:創建型設計模式(上)
下一篇:設計模式-行為型-職責鏈模式
