命令模式:将请求封装在对象中,客户不直接调用某个对象的方法,而是使用命令,将命令传递给拥有方法的对象从而让某一方法被调用。UML图如下:
下面是用C++描写的命令模式的一个简单例子:
#include <iostream>
#include <string>
#include <list>
using namespace std;
// Interface
class Command {
public:
virtual void Execute() = 0;
};
/* Invoker命令发送者 */
class Switch {
public:
// 存储命令
void Add(Command *command)
{
commands.push_back(command);
}
// 删除命令
void Remove(Command *command)
{
commands.remove(command);
}
// 执行所有命令的发送
void Execute()
{
list<Command*>::iterator iter = commands.begin();
for (; iter != commands.end(); ++iter)
{
(*iter)->Execute();
}
}
private:
list<Command*> commands;
};
/* The Receiver class */
class Light {
public:
void TurnOn()
{
cout << "The light is on" << endl;
}
void TurnOff()
{
cout << "The light is off" << endl;
}
};
/* The Command for turning on the light - ConcreteCommand #1 */
class FlipUpCommand : public Command {
public:
FlipUpCommand(Light light)
{
light = light;
}
void Execute()
{
light.TurnOn();
}
private:
Light light; // 命令中包含命令接收者
};
/* The Command for turning off the light - ConcreteCommand #2 */
class FlipDownCommand : public Command {
public:
FlipDownCommand(Light light)
{
light = light;
}
void Execute()
{
light.TurnOff();
}
private:
Light light; // 命令中包含命令接收者
};
int main()
{
Light light; // 灯有‘开’、‘关’两种操作
Command *up = new FlipUpCommand(light); // ‘开’命令
Command *down = new FlipDownCommand(light); // ‘关’命令
Switch sw;
sw.Add(up); // 命令交给开关
sw.Add(down); // 命令交给开关
sw.Execute(); // 开关执行命令
sw.Remove(up);
sw.Execute(); // 开关执行命令
system("pause");
return 0;
}
运行结果:
命令被封装成类,然后由某个Invoker(这里是switch开关类)保存、删除、发出命令。命令行的优点在于:把请求一个操作的对象(Invoker)与知道怎么执行一个操作的对象(Receiver)分隔开了。我们可以在实际操作开始之前或之后进行某些灵活的操作,比如:添加、删除、重复、记录日志等。
参考:
维基百科
《大话设计模式》第23章