設計模式筆記—21_Command命令模式

Command命令模式是一種“行爲變化”模式

  • 在組件的構建過程中,組件行爲的變化經常導致組件本身劇烈的變化。“行爲變化”模式將組件的行爲和組件本身進行解耦,從而支持組件行爲的變化,實現兩者之間的松耦合

動機

  • 在軟件構建過程中,“行爲請求者”與“行爲實現者”通常呈現出一種“緊耦合”。但在某些場合——比如需要對行爲進行“記錄/撤銷/重(undo/redo)/事務”等處理,這種無法抵禦變化的緊耦合是不合適的
  • 在這種情況下,如何將“行爲請求者”與“行爲實現者”解耦?將一組行爲抽象爲對象,可以實現兩者之間的松耦合

定義

  • 將一個請求(行爲)封裝爲一個對象,從而使你可以用不同的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷的操作

結構

在這裏插入圖片描述

代碼對比

command.cpp

#include <iostream>
#include <vector>
#include <string>
using namespace std;


class Command
{
public:
    virtual void execute() = 0;
};

class ConcreteCommand1 : public Command
{
    string arg;
public:
    ConcreteCommand1(const string & a) : arg(a) {}
    void execute() override
    {
        cout<< "#1 process..."<<arg<<endl;
    }
};

class ConcreteCommand2 : public Command
{
    string arg;
public:
    ConcreteCommand2(const string & a) : arg(a) {}
    void execute() override
    {
        cout<< "#2 process..."<<arg<<endl;
    }
};
        
        
class MacroCommand : public Command
{
    vector<Command*> commands;
public:
    void addCommand(Command *c) { commands.push_back(c); }
    void execute() override
    {
        for (auto &c : commands)
        {
            c->execute();
        }
    }
};
        

        
int main()
{

    ConcreteCommand1 command1(receiver, "Arg ###");
    ConcreteCommand2 command2(receiver, "Arg $$$");
    
    MacroCommand macro;
    macro.addCommand(&command1);
    macro.addCommand(&command2);
    
    macro.execute();

}

對比

  • 繼承了抽象基類Command的派生類,表現出來的就是一種具體的行爲。甚至可以定義一些宏命令MacroCommand

要點總結

  • Command模式的根本目的在於將“行爲請求者”和“行爲實現者”解耦,在面嚮對象語言中,常見的實現手段是“將行爲抽象爲對象”
  • 實現Command接口的具體命令對象ConcreteCommand有時候根據需要可能會保存一些額外的狀態信息。通過使用Composite模式,可以將多個“命令”封裝成一個“複合命令”MacroCommand
  • Command模式與C++中的函數對象有些類似。但兩者定義行爲接口的規範有所區別:Command以面向對象中的“接口-實現”來定義行爲接口規範,更嚴格,但有性能損失;C++函數對象以函數簽名來定義行爲接口規範,更靈活,性能更高
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章