概念
Command模式也叫命令模式,是行为设计模式的一种,Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。
在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建目标对象实例-->设置调用参数-->抵用目标对象的方法。
但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。
整个调用过程比较复杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。
调用前后需要对调用参数进行某些处理,调用前后需要进行某些额外处理:比如日志,缓存,记录历史操作等。
命令模式结构图
示例代码
#include <iostream>
#include <list>
using namespace std;
class Doctor
{
public:
void treatEye()
{
cout<<"doctor treat eye!"<<endl;
}
void treatNouse()
{
cout<<"doctor treat nouse!"<<endl;
}
};
class Command
{
public:
Command() {}
virtual ~Command() {}
virtual void treat() = 0;
};
class CommandTreatEye : public Command
{
public:
CommandTreatEye(Doctor* doctor)
{
m_doctor = doctor;
}
void treat()
{
m_doctor->treatEye();
}
private:
Doctor* m_doctor;
};
class CommandTreatNouse : public Command
{
public:
CommandTreatNouse(Doctor* doctor)
{
m_doctor = doctor;
}
void treat()
{
m_doctor->treatNouse();
}
private:
Doctor* m_doctor;
};
class BeautyNurse
{
public:
BeautyNurse(Command* command)
{
m_command = command;
}
void submittedCase() //提交病例(下达命令)
{
m_command->treat();
}
private:
Command* m_command;
};
//护士长
class HeadNurse
{
public:
HeadNurse()
{
m_list.clear();
}
void setCommand(Command* cmd)
{
m_list.push_back(cmd);
}
void submittedCase() //提交病例(下达命令)
{
list<Command*>::iterator it = m_list.begin();
while( it != m_list.end() )
{
(*it)->treat();
++it;
}
}
private:
list<Command*> m_list;
};
int main_1()
{
HeadNurse* pHeadNurse = NULL;
Doctor* pDoctor = NULL;
Command* pCommandTreatEye = NULL;
Command* pCommandTreatNouse = NULL;
pDoctor = new Doctor();
pCommandTreatEye = new CommandTreatEye(pDoctor);
pCommandTreatNouse = new CommandTreatNouse(pDoctor);
pHeadNurse = new HeadNurse();
pHeadNurse->setCommand(pCommandTreatEye);
pHeadNurse->setCommand(pCommandTreatNouse);
pHeadNurse->submittedCase();
delete pDoctor;
delete pCommandTreatEye;
delete pCommandTreatNouse;
delete pHeadNurse;
return 0;
}
int main(int argc, char* argv[])
{
(void)argc,(void)argv;
BeautyNurse* pBeautyNurse = NULL;
Doctor* pDoctor = NULL;
Command* pCommand = NULL;
pDoctor = new Doctor();
//pCommand = new CommandTreatEye(pDoctor);
pCommand = new CommandTreatNouse(pDoctor);
pBeautyNurse = new BeautyNurse(pCommand);
pBeautyNurse->submittedCase();
delete pDoctor;
delete pCommand;
delete pBeautyNurse;
cout<<"******************"<<endl;
main_1();
return 0;
}
运行结果
命令模式优点
- 类间解耦:调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command 抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。
- 可扩展性:Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严 重的代码耦合。
- 命令模式结合其他模式会更优秀:命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题。
命令模式缺点
命令模式也是有缺点的,请看Command的子类:如果有N个命令,问题就出来 了,Command的子类就可不是几个,而是N个,这个类膨胀得非常大,这个就需要读者在项 目中慎重考虑使用。