在軟件構建過程中,“行為請求者”與“行為實現者”通常呈現一種“緊耦合”。但在某些場合,比如需要對行為進行“記錄、撤銷/重做(undo/redo)、事務”等處理,這種無法抵御變化的緊耦合是不合適的。Command設計模式就是在這種情況下,將“行為請求者”與“行為實現者”解耦,將一組行為抽象為對象,以實現二者之間的松耦合。 “Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.” – GoF 將一個請求封裝為一個對象,從而可用不同的請求(一個被封裝成了對象的請求)對客戶程序(即調用者)進行參數化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。www.2cto.com 實例分析,實際工作中,我們遇到了很多文檔,都支持回退/前進的功能,它們快捷鍵也是驚人的相似Ctrl+z與Ctrl+y。下面將用一段代碼來實現其操作,其原理就是命令模式。 [cpp] www.2cto.com #include <iostream> #include <stack> class Receiver { private: std::string str; public: std::string get_str(){ return str; } void set_str(const std::string& s){ str=s; } void append(std::string astr){ str.append(astr); } void show(){ std::cout<<str<<std::endl; } }; class Command { public: virtual void execute()=0; Command(Receiver *re,const std::string& p) :r(re),par(p) {} virtual ~Command(){} protected: Receiver * r; std::string par; }; class UndoCommand:public Command { public: UndoCommand(Receiver *re,const std::string& p) :Command(re,p) {} virtual void undo()=0; virtual void redo()=0; virtual ~UndoCommand(){} }; class ConcreteCommand:public UndoCommand { public: ConcreteCommand(Receiver *re,const std::string& p) :UndoCommand(re,p) {} void execute() { preStr=r->get_str(); r->append(par); curStr=r->get_str(); } void undo() { r->set_str(preStr); } void redo() { r->set_str(curStr); } private: std::string preStr; std::string curStr; }; class ConcreteManager { private: std::stack<Command*> exeComStack; std::stack<Command*> undoComStack; public: void executeCommand(Command* cmd); void undoCommand(); void redoCommand(); ~ConcreteManager(); }; ConcreteManager::~ConcreteManager() { while(exeComStack.size()>0) { delete exeComStack.top(); exeComStack.pop(); } while(undoComStack.size()>0) { delete undoComStack.top(); undoComStack.pop(); } } void ConcreteManager::executeCommand(Command* cmd) { cmd->execute(); exeComStack.push(cmd); } void ConcreteManager::undoCommand() { if(exeComStack.size()>0) { UndoCommand *cmd =dynamic_cast<UndoCommand*>(exeComStack.top()); exeComStack.pop(); cmd->undo(); undoComStack.push(cmd); } } void ConcreteManager::redoCommand() { if(undoComStack.size()>0) { UndoCommand * cmd=dynamic_cast<UndoCommand*>(undoComStack.top()); undoComStack.pop(); cmd->redo(); exeComStack.push(cmd); } } int main(int argc,char** argv) { ConcreteManager *co=new ConcreteManager; Receiver* re=new Receiver; Command* cm1=new ConcreteCommand(re,"hu"); Command* cm2=new ConcreteCommand(re,"cs"); Command* cm3=new ConcreteCommand(re,"dn"); Command* cm4=new ConcreteCommand(re,"!!"); co->executeCommand(cm1); co->executeCommand(cm2); co->executeCommand(cm3); co->executeCommand(cm4); re->show(); co->undoCommand(); co->undoCommand(); co->undoCommand(); re->show(); co->redoCommand(); co->redoCommand(); co->redoCommand(); co->redoCommand(); re->show(); delete re; delete co; return 0; } 運行結果 singleton pattern--單件模式 factory mothed pattern--工廠方法模式 abstract factory pattern--抽象工廠模式 builder pattern--建造者模式 prototype pattern--原型模式 adapter pattern--適配器模式 bridge pattern -- 橋接模式 composite pattern -- 組合模式 decorator pattern -- 裝飾模式 decorator pattern -- 享元模式 decorator pattern -- 代理模式 decorator pattern -- 責任鏈模式 decorator pattern -- 命令模式