預約“大牌”的困擾
我有一個朋友,他是個大忙人,每天的行程表都是塞得滿滿的,要預約他可不容易。關鍵是,剛開始他還是邋里邋遢的,並沒有一個明確的日程表。這就導致了三個問題:
1、我們不知道什麼時候可以約他,就只能直接把預約請求扔給他。
2、他有時候都不知道回覆我們的預約,有時候預約了他又忘記了,忙嘛。
3、我們不方便單方面解約,畢竟人家百忙之中還抽空出來嘛。
後來,他有了祕書。
1、我們預約他,給他的祕書說一下就好。
2、他的祕書會提醒他佳人有約。
3、我們要取消約定,跟他的祕書說一下就好了。
真是大牌,祕書都用上了。
這裏又隱藏着一個設計模式 – 命令模式
命令模式
命令模式:將一個請求封裝成一個對象,從而可以使你用不同的請求對客戶進行參數化、對請求排隊或記錄請求日誌、以及支持可撤銷的操作。
上面這圖可能抽象了點啊,沒事兒,咱不是有故事嘛。
再來一張就是了。
小故事的代碼完整實現
這裏囊括瞭解約、記錄、針對不同任務等模塊,我在網上其他地方是沒找到用C++有實現這個的。
#include<iostream>
#include<list>
using namespace std;
//大忙人類
class BusyMan {
public:
void Dinner() { cout << "晚餐" << endl; }
void Game() { cout << "打遊戲" << endl; }
};
//抽象命令類
class AbsCommand {
protected :
BusyMan *man;
string state; //命令參數
public:
AbsCommand(BusyMan* man) { this->man = man; }
string getState() { return state; }
//執行命令
virtual void excuteCommand() = 0;
};
//吃晚飯預約
class DinnerCommand :public AbsCommand {
public:
DinnerCommand(BusyMan* man) :AbsCommand(man) { this->state = "晚飯"; };
void excuteCommand() {
man->Dinner();
}
};
//打遊戲預約
class GameCommand :public AbsCommand {
public:
GameCommand(BusyMan* man) :AbsCommand(man) { this->state = "打遊戲"; };
void excuteCommand() {
man->Game();
}
};
//祕書類
class selary {
private:
list<AbsCommand*> AC;
public:
//安排預約
void SetOrder(AbsCommand* abs) {
if (abs->getState() == "晚飯")
cout << "沒空" << endl;
else
{
AC.push_back(abs);
cout << "預約成功,請於XX:XX準時上線快樂雙排" << endl;
//這裏可以再加個寫入配置文件的
}
}
//解約
void cancelOrder(AbsCommand* abs){
AC.remove(abs);
cout << "解約成功" << endl;
}
void notify(){
list<AbsCommand*>::iterator it = AC.begin();
while (it != AC.end())
{
(*it)->excuteCommand();
it++;
}
AC.clear();
}
};
int main()
{
BusyMan* man = new BusyMan();
AbsCommand* d = new DinnerCommand(man);
AbsCommand* g1 = new GameCommand(man);
AbsCommand* g2 = new GameCommand(man);
selary* s = new selary();
s->SetOrder(d);
s->SetOrder(g1);
s->notify();
s->SetOrder(g1);
s->SetOrder(g2);
s->cancelOrder(g1);
s->notify();
return 0;
}
應用場景
命令模式通常適用於以下場景。
當系統需要將請求調用者與請求接收者解耦時,命令模式使得調用者和接收者不直接交互。
當系統需要隨機請求命令或經常增加或刪除命令時,命令模式比較方便實現這些功能。
當系統需要執行一組操作時,命令模式可以定義宏命令來實現該功能。
當系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作時,可以將命令對象存儲起來,採用備忘錄模式來實現。