16. Command(命令)
16.1 定義
將一個請求封裝成一個對象,從而讓你使用不同的請求把客戶端參數化,對請求排隊或者記錄請求日志,可以提供命令的撤銷和恢復功能。
16.2.優點
■ 類間解耦。調用者角色與接收者角色之間沒有任何依賴關系,調用者實現功能時只需要調用Command中的execute()方法即可,不需要了解是哪個接收者執行。
■ 可擴展性。Command 的子類可以非常容易地擴展,而調用者Invoker和高層次的模塊Client不產生嚴重的代碼耦合。
■ 命令模式結合其他模式會更優秀。命令模式可以結合責任鏈模式,實現命令族解析任務,結合模板方法模式,則可以減少Command子類的膨脹問題。
16.3 缺點
■ 使用命令模式可能會導致系統中出現過多的具體命令類,因此需要在項目中慎重考慮使用。
16.4 應用場景
■ 使用命令模式作為“回調”在面向對象系統中的替代。“回調”講的便是將一個函數登記上,然后在以后調用此函數。
■ 需要在不同的時間指定請求、將請求排隊。
■ 系統需要支持命令的撤銷(undo)。命令對象可以把狀態存儲起來,等到客戶端需要撤銷時,可以調用undo()方法,將命令所產生的效果撤銷。
■ 需要將系統中所有的數據更新操作保存到日志里,以便在系統崩潰時,可以根據日志讀回所有的數據更新命令,重新調用 execute()方法一條一條執行這些命令,從而恢復系統在崩潰前所做的數據更新。
■ 一個系統需要支持交易(transaction)。一個交易結構封裝了一組數據更新命令。使用命令模式來實現交易結構可以使系統增加新的交易類型
1 #include<iostream> 2 #include<list> 3 using namespace std; 4 class Order{ 5 public: 6 virtual void execute() = 0; 7 }; 8 class Stock{ 9 private: 10 string name = "ABC"; 11 int quantity = 10; 12 public: 13 void buy(){ 14 cout<<"Stock [ Name: "+name+" Quantity: " << quantity <<" ] bought"<<endl; 15 } 16 void sell(){ 17 cout<<"Stock [ Name: "+name+" Quantity: " << quantity <<" ] sold"<<endl; 18 } 19 }; 20 class BuyStock:public Order{ 21 private: 22 Stock abcStock; 23 public: 24 BuyStock(Stock abcStock){ 25 this->abcStock = abcStock; 26 } 27 void execute() { 28 abcStock.buy(); 29 } 30 }; 31 class SellStock:public Order { 32 private: 33 Stock abcStock; 34 35 public: 36 SellStock(Stock abcStock){ 37 this->abcStock = abcStock; 38 } 39 40 void execute() { 41 abcStock.sell(); 42 } 43 }; 44 45 class Broker { 46 private: 47 list<Order*> orderList; 48 public: 49 void takeOrder(Order* order){ 50 orderList.push_back(order); 51 } 52 53 void placeOrders(){ 54 list<Order*>::iterator iter = orderList.begin(); 55 for (; iter != orderList.end(); iter++){ 56 (*iter)->execute(); 57 delete (*iter); 58 } 59 orderList.clear(); 60 } 61 }; 62 63 int main(){ 64 Stock abcStock; 65 Order* buyStockOrder = new BuyStock(abcStock); 66 Order* sellStockOrder = new SellStock(abcStock); 67 Broker broker; 68 broker.takeOrder(buyStockOrder); 69 broker.takeOrder(sellStockOrder); 70 broker.placeOrders(); 71 delete buyStockOrder; 72 buyStockOrder = NULL; 73 delete sellStockOrder; 74 sellStockOrder = NULL; 75 }