設計模式介紹之三:命令模式(command)
阿新 • • 發佈:2019-02-10
命令(模式)的結構很簡單,但對於消除程式碼間的耦合卻有著重要的影響。
在 C 語言中我們經常使用回撥函式,而命令模式是回撥( callback )的面向物件的替代物。從最直觀的角度來看,命令模式就是一個函式物件:一個作為物件的函式。通過將函式封裝為物件,就能夠以引數的形式將其傳遞給其他函式或者物件,告訴他們在履行請求的過程中執行特定的操作。可以說,命令模式是攜帶行為資訊的信使。
命令模式對於構建 GUI 應用有特別重要的意義,比如選單的響應,使用 MFC 時我們通過一系列的 on_command 巨集來關聯選單操作,而如果採用命令模式和工廠模式,將可以得到更精巧的實現。
意圖
- 將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日誌,以及支援可撤消的操作。
- Qt , QAction
- Command 物件生命週期維護
- 抽象出待執行的動作以引數化某物件。
- 在不確定的時刻指定、排列和執行請求
- 支援取消操作
- 支援修改日誌
- 用構建在原語操作上的高層操作構造一個系統
- 不關注怎樣執行,只關注有物件可以接受執行請求
我們可以把 EchoCommand 和 HelloCommand 兩個命令物件傳遞出去,其他部分的程式碼只需要知道在特定條件發生時有物件執行命令,而無需知道是誰、在執行什麼命令。class CommandObject { public: CommandObject(){} virtual ~CommandObject(){} virtual void execute() = 0; }; class EchoCommand: public CommandObject { public: void execute() { cout << "I\'m echo command"; } }; class HelloCommand: public CommandObject { public: void execute() { cout << "Hello hello, how are you"; } };
接下來看另外一個有點實際意義的例子。假如我們實現一個 GUI 程式,主頁面上有多個按鈕,點選按鈕後會執行一個命令,如開啟新視窗、開啟瀏覽器、開啟資料夾、退出程式之類的。
命令模式例項2
我們可以把按鈕的資訊寫在配置檔案中,如名字、圖示、位置等,而每個按鈕要執行的命令通過一個字串表示,也寫在配置檔案中。程式啟動時解析配置檔案,生成介面,根據配置檔案中的命令字串通過工廠模式建立一個命令物件並與按鈕關聯(如上面的程式碼所示,通過 setCommandObject 方法給按鈕設定命令物件),這樣一個極具擴充套件性的程式就完成了。class CPushButton : public IButton { public: void setCommandObject(CommandObject * commandObject){ if(m_pCommand) { delete m_pCommand; } m_pCommand = commandObject; } void onClicked() { m_pCommand->execute(); } private: CommandObject * m_pCommand; };
接下來會介紹工廠模式,結合單例模式、命令模式,實現一個有意義的例子。