命令模式
模式定義
命令模式(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;
}
- 執行結果
魚香肉絲
宮保雞丁
大盤雞
優點
命令模式的優點
- 它能較容易的設計一個命令佇列;
- 在需要的情況下,可以較容易的將命令計入日誌;
- 允許接收請求的一方決定是否要否決請求;
- 可以容易的實現對請求的撤銷和重做;
- 由於加進新的具體命令類不影響其他的類,因此增加新的具體命令類很容易;
- 把請求一個操作的物件與知道怎麼執行一個操作的物件分隔開;
缺點
模式的缺點