题目描述:
Command
动机(Motivation)
- ”行为请求者“与”行为实现者“通常呈现一种”紧耦合“。但在某些场合——比如需要对行为进行”记录、撤销、事务“等处理,这种无法抵御变化的紧耦合是不合适的。
- 在这种情况下,如何将”行为请求者“与”行为实现者“解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。
模式定义
将一个请求(行为)封装成一个对象,从而使你可用不用的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
——《设计模式》GoF
要点总结
- Command模式的根本目的在于将”行为请求者“与”行为实现者“解耦,在面向对象语言中,常见的实现手段是”将行为抽象为对象“。
- 与C++中的函数对象类似,C++函数对象以函数签名来定义行为接口规范,更灵活性能更高。
代码结构
.
├── build.sh
├── clearBuild.sh
├── CMakeLists.txt
├── src
│ ├── examStu.cpp
│ ├── include
│ │ └── examStu.h
│ └── main.cpp
源码例子
examStu.h
#ifndef _EXANSTU__
\#define _EXANSTU__
\#include <iostream>
\#include <string>
\#include <vector>
\#include <list>
using namespace std;
class chef
{
public:
chef()=default;
void MakeNoodles()
{
cout<< "chef Make Noodles "<<endl;
}
void MakePizza()
{
cout<< "chef Make Pizza "<<endl;
}
private:
};
class CookCommand
{
public:
CookCommand(chef* p):pchef(p){
}
virtual ~CookCommand(){
};
virtual void ExecuteCommand() = 0;
protected:
chef * pchef;
};
class NoodlesCommand:public CookCommand
{
public:
NoodlesCommand(chef * p):CookCommand(p){
}
void ExecuteCommand()
{
pchef->MakeNoodles();
}
private:
};
class PizzaCommand:public CookCommand
{
public:
PizzaCommand(chef * p):CookCommand(p){
}
void ExecuteCommand()
{
pchef->MakePizza();
}
private:
};
class Waiter
{
public:
Waiter()=default;
~Waiter(){
};
void AddCommand(CookCommand * pCmd)
{
pCmdVec.push_back(pCmd);
}
void submitCmd()
{
for(auto it=pCmdVec.begin();it!=pCmdVec.end();it++)
{
(*it)->ExecuteCommand();
}
}
private:
std::vector<CookCommand *> pCmdVec;
};
#endif
main.cpp
#include <iostream>
\#include <string>
\#include <memory>
\#include "examStu.h"
using namespace std;
int main()
{
Waiter * pWaiter= new Waiter();
chef * pchef= new chef();
CookCommand * pNoodlesCommand= new NoodlesCommand(pchef);
CookCommand * pPizzaCommand= new PizzaCommand(pchef);
pWaiter->AddCommand(pNoodlesCommand);
pWaiter->AddCommand(pPizzaCommand);
pWaiter->submitCmd();
delete pWaiter;
delete pchef;
delete pNoodlesCommand;
delete pPizzaCommand;
return 0;
}
另外一种写法如下:
examStu.c
#ifndef _EXANSTU__
#define _EXANSTU__
#include <iostream>
#include <string>
#include <vector>
#include <list>
using namespace std;
class chef
{
public:
chef()=default;
void MakeNoodles()
{
cout<< "chef Make Noodles "<<endl;
}
void MakePizza()
{
cout<< "chef Make Pizza "<<endl;
}
private:
};
class CookCommand
{
public:
CookCommand(){
}
virtual ~CookCommand(){
};
virtual void ExecuteCommand() = 0;
protected:
};
class NoodlesCommand:public CookCommand
{
public:
NoodlesCommand(chef * p):pchef(p){
}
void ExecuteCommand()
{
pchef->MakeNoodles();
}
private:
chef * pchef;
};
class PizzaCommand:public CookCommand
{
public:
PizzaCommand(chef * p):pchef(p){
}
void ExecuteCommand()
{
pchef->MakePizza();
}
private:
chef * pchef;
};
class Waiter
{
public:
Waiter()=default;
~Waiter(){
};
void AddCommand(CookCommand * pCmd)
{
pCmdVec.push_back(pCmd);
}
void submitCmd()
{
for(auto it=pCmdVec.begin();it!=pCmdVec.end();it++)
{
(*it)->ExecuteCommand();
}
}
private:
std::vector<CookCommand *> pCmdVec;
};
#endif
main.c
#include <iostream>
#include <string>
#include <memory>
#include "examStu.h"
using namespace std;
int main()
{
Waiter * pWaiter= new Waiter();
chef * pchef= new chef();
CookCommand * pNoodlesCommand= new NoodlesCommand(pchef);
CookCommand * pPizzaCommand= new PizzaCommand(pchef);
pWaiter->AddCommand(pNoodlesCommand);
pWaiter->AddCommand(pPizzaCommand);
pWaiter->submitCmd();
delete pWaiter;
delete pchef;
delete pNoodlesCommand;
delete pPizzaCommand;
return 0;
}