命令模式(c++實現)

鬼谷子com發表於2020-07-15

命令模式

模式定義

命令模式(Command),將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日誌,以及支援可撤銷的操作。

模式動機

  • 敏捷開發的原則告訴我們,不要為程式碼新增基於猜測的、實際不需要的功能。如果不清楚一個系統是否需要命令模式,一般就不要著急去實現它,事實上,在需要的時候通過重構實現這個模式並不困難,只有在真正需要如撤銷/恢復操作等功能時,把原來的程式碼重構為命令模式才有意義。

UML類圖

原始碼實現

  • command.h
#include "chef.h"

class Command
{
public:
    Command(Chef* chef);
    virtual ~Command();
    virtual void ExcuteCmd();

protected:
    Chef*   m_Chef;
};
  • chef.h
class Chef
{
public:
    Chef();
    void KungPaoChicken();
    void FishFlavoredShreddedPork();
    void BigPlateChicken();
};
  • chef.cpp
#include "chef.h"
#include <iostream>
Chef::Chef()
{

}

void Chef::KungPaoChicken()
{
    std::cout << "宮保雞丁" << std::endl;
}

void Chef::FishFlavoredShreddedPork()
{
    std::cout << "魚香肉絲" << std::endl;
}

void Chef::BigPlateChicken()
{
    std::cout << "大盤雞" << std::endl;
}

  • kungpaochickencmd.h
#include "command.h"
#include "chef.h"

class KungPaoChickenCmd : public Command
{
public:
    KungPaoChickenCmd(Chef* chef);
    void ExcuteCmd() override;
};
  • kungpaochickencmd.cpp
#include "kungpaochickencmd.h"

KungPaoChickenCmd::KungPaoChickenCmd(Chef* chef)
    :Command(chef)
{

}

void KungPaoChickenCmd::ExcuteCmd()
{
    m_Chef->KungPaoChicken();
}
  • waiter.h
#include <list>
#include <command.h>

class Waiter
{
public:
    Waiter();
    void AddCmd(Command* cmd);
    void DelCmd(Command* cmd);
    void Nodify();
private:
    std::list<Command*>     m_CmdList;
};
  • waiter.cpp
#include "waiter.h"

Waiter::Waiter()
{

}

void Waiter::AddCmd(Command *cmd)
{
    m_CmdList.push_back(cmd);
}

void Waiter::DelCmd(Command *cmd)
{
    m_CmdList.remove(cmd);
}

void Waiter::Nodify()
{
    for(auto cmd : m_CmdList)
    {
        if(cmd)
            cmd->ExcuteCmd();
    }
}
  • main.cpp
#include <iostream>
#include "fishflavoredshreddedporkcmd.h"
#include "kungpaochickencmd.h"
#include "bigplatechickencmd.h"
#include "waiter.h"
#include <memory>
int main()
{
    Chef* chef = new Chef();
    Waiter waiter;

    std::shared_ptr<FishFlavoredShreddedPorkCmd> ffspc = std::make_shared<FishFlavoredShreddedPorkCmd>(chef);
    std::shared_ptr<KungPaoChickenCmd> kpcc = std::make_shared<KungPaoChickenCmd>(chef);
    std::shared_ptr<BigPlateChickenCmd> bpcc = std::make_shared<BigPlateChickenCmd>(chef);

    waiter.AddCmd(ffspc.get());
    waiter.AddCmd(kpcc.get());
    waiter.AddCmd(bpcc.get());
    //        waiter.DelCmd(kpcc.get);

    waiter.Nodify();
    return 0;
}

  • 執行結果

魚香肉絲

宮保雞丁

大盤雞

優點

命令模式的優點

  • 它能較容易的設計一個命令佇列;
  • 在需要的情況下,可以較容易的將命令計入日誌;
  • 允許接收請求的一方決定是否要否決請求;
  • 可以容易的實現對請求的撤銷和重做;
  • 由於加進新的具體命令類不影響其他的類,因此增加新的具體命令類很容易;
  • 把請求一個操作的物件與知道怎麼執行一個操作的物件分隔開;

缺點

模式的缺點

相關文章