1、命令模式概述:
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化。这样可以将调用操作的对象与知道如何实现这些操作的对象分离。命令模式涉及到五个角色:
- 抽象命令(Command):声明了命令接口,通常包含一个名为Execute的方法。
- 具体命令(ConcreteCommand):实现抽象命令接口,定义了具体的执行方法。
- 请求者(Invoker):负责调用命令对象执行请求,通常不需要知道命令的具体实现。
- 接收者(Receiver):是命令执行的具体实现者,负责执行相关操作。
- 客户端(Client):创建具体的命令对象并设置接收者。
2、命令模式的适用场景:
- 当需要将请求者与实现请求的对象解耦时。
- 当需要支持撤销(undo)和恢复(redo)操作时。
- 当需要在不同时间点执行不同的请求时,例如队列和调度任务。
- 当需要将一组操作组合为一个复合操作时。
3、命令模式的优点:
- 解耦:命令模式使请求者与实现者解耦,使得调用者不需要知道命令的实现细节。
- 扩展性:可以方便地添加新的命令和实现,而不需要修改现有代码。
- 组合:可以将多个命令组合成一个复合命令,实现更复杂的功能。
- 支持撤销和恢复操作。
举例说明:例如一个遥控器(请求者)可以控制电视、空调等多种设备(接收者),通过命令模式,可以轻松地添加新的设备或控制命令,同时实现撤销和恢复操作。
4、命令模式的缺点:
- 命令数量增多:对于每个具体的操作,都需要实现一个具体的命令类,这会导致系统中类的数量增加,增加了系统的复杂性。
- 命令对象开销:如果命令对象太多,可能会导致系统资源消耗较大。
举例说明:在一个复杂的应用程序中,如果每个操作都需要一个具体的命令类,那么随着操作数量的增加,项目的复杂度和维护成本也会增加。同时,如果每个命令都需要创建一个对象,会导致系统资源消耗增加。
5、用C++实现一个命令模式例子:
#include <iostream>
#include <memory>
// 抽象命令类
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
// 接收者类
class Light {
public:
void on() {
std::cout << "Light is on." << std::endl;
}
void off() {
std::cout << "Light is off." << std::endl;
}
};
// 具体命令类 - 开灯
class LightOnCommand : public Command {
public:
LightOnCommand(std::shared_ptr<Light> light) : light_(light) {}
void execute() override {
light_->on();
}
private:
std::shared_ptr<Light> light_;
};
// 具体命令类 - 关灯
class LightOffCommand : public Command {
public:
LightOffCommand(std::shared_ptr<Light> light) : light_(light) {}
void execute() override {
light_->off();
}
private:
std::shared_ptr<Light> light_;
};
// 请求者类
class RemoteControl {
public:
void setCommand(std::shared_ptr<Command> command) {
command_ = command;
}
void pressButton() {
command_->execute();
}
private:
std::shared_ptr<Command> command_;
};
int main() {
// 创建接收者
auto light = std::make_shared<Light>();
// 创建命令
auto lightOn = std::make_shared<LightOnCommand>(light);
auto lightOff = std::make_shared<LightOffCommand>(light);
// 创建请求者
RemoteControl remote;
// 设置命令并执行
remote.setCommand(lightOn);
remote.pressButton(); // 输出:Light is on.
remote.setCommand(lightOff);
remote.pressButton(); // 输出:Light is off.
return 0;
}
在这个例子中,我们创建了一个Light类作为接收者,它有两个操作:on()和off()。然后,我们创建了两个具体的命令类LightOnCommand和LightOffCommand,分别用于开灯和关灯。RemoteControl类充当请求者,负责调用命令对象执行请求。在main函数中,我们创建了接收者、命令和请求者对象,并将命令对象设置到请求者,然后通过调用请求者的pressButton()方法来执行命令。