一、引言
命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使用户可以使用不同的请求、队列或日志来参数化其他对象。通过命令模式,程序可以实现请求的排队、记录请求日志以及支持可撤销操作。
二、使用场景
-
需要支持撤销和重做操作:命令模式非常适合处理那些需要提供撤销功能的场景,例如在文本编辑器中执行的多个操作。
-
请求调用的调用者与接受者之间的解耦:在需要将请求的发送者与处理者解耦的情况下,命令模式提供一种有效的方式。
-
宏命令的执行:当需要在一系列操作中进行特定操作的组合时,命令模式可以利用命令对象批量处理相关操作。
-
请求的参数化:可以使用命令对象通过不同的参数化请求进行不同的处理,增强了灵活性和可扩展性。
三、模式分类
-
简单命令模式:有简单的操作请求,包含所有操作的访问和调用接口。
-
组合命令模式:允许多个命令合并形成一个更复杂的操作,用于执行一系列命令。
-
宏命令模式:用于将一组命令包装成一个命令并按照顺序依次执行。
四、优缺点
优点
- 解耦:命令模式将请求的发送者与执行者之间的耦合打散,方便代码的扩展及维护。
- 增强的灵活性:可以根据需要在不同场合配置和修改命令执行,不需要对现有的代码做太多改动。
- 支持撤销的操作:通过堆栈模式运用命令模式实现的撤销操作显得尤为简单。
缺点
- 增加系统复杂性:命令模式可能导致类的数量互相交叉,一定逻辑的下游请求、响应有时难以骨骼清晰。
- 难以实现:在涉及更复杂的命令对象时,可能需提供请求的具体细节,让实现变得更加复杂。
- 命令结构可能庞大:如果实现的命令过多,可能导致命令体庞大并变得难以维护和扩展。
五、代码示例
以下是命令模式的C++实现示例。
#include <iostream>
#include <memory>
#include <vector>
// 命令接口
class Command {
public:
virtual void execute() = 0; // 执行命令的接口
virtual ~Command() = default; // 虚析构函数
};
// 示例接收者类 (开灯)
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 {
private:
Light* light; // 接收者
public:
LightOnCommand(Light* light) : light(light) {} // 设置接收者
void execute() override {
light->on(); // 调用接收者的逻辑
}
};
// 具体命令类
class LightOffCommand : public Command {
private:
Light* light; // 接收者
public:
LightOffCommand(Light* light) : light(light) {} // 设置接收者
void execute() override {
light->off(); // 调用接收者的逻辑
}
};
// 遥控器 (用来保存命令)
class RemoteControl {
private:
std::vector<std::shared_ptr<Command>> commandList; // 命令存储列表
public:
void addCommand(std::shared_ptr<Command> command) {
commandList.push_back(command); // 添加命令
}
void pressButton(int index) {
if (index < commandList.size()) {
commandList[index]->execute(); // 执行命令
}
else {
std::cout << "No command assigned to this button!" << std::endl;
}
}
};
int main() {
// 创建接收者
auto light = std::make_unique<Light>(); // 使用 unique_ptr
// 创建具体命令
std::shared_ptr<Command> lightOn = std::make_shared<LightOnCommand>(light.get());
std::shared_ptr<Command> lightOff = std::make_shared<LightOffCommand>(light.get());
// 创建遥控器并设置命令
RemoteControl remote;
remote.addCommand(lightOn); // 将命令设置为打开灯的命令
remote.addCommand(lightOff); // 将命令设置为关闭灯的命令
// 模拟按下开灯按钮
remote.pressButton(0); // 输出 "Light is ON!"
// 模拟按下关灯按钮
remote.pressButton(1); // 输出 "Light is OFF!"
return 0; // unique_ptr will automatically clean up light
}
代码解析
-
Command 接口:定义了一种统一的命令接口,通过
execute()
方法用于执行命令。 -
LightOnCommand 和 LightOffCommand:具体的命令类,负责定义打开和关闭灯的命令。命令类持有接收者(通过 light )对象的引用并执行相关逻辑。
-
RemoteControl:中控器类,作为命令的接收和存储器,管理命令对象并提供按下按钮执行的方式。
-
main() 函数:借助
RemoteControl
设定命令,通过pressButton()
方法执行命令,并显示相应的操作信息。
六、模式总结
命令模式解决了请求的发送者与处理者之间的耦合,是对象请求机制中不可或缺的一部分。它的自主性使得请求能有多种处理方案,且便于复杂请求重用。虽然引入了新的类并增大了应用的复杂度,但在合适的场合使用,它依然能够增强代码的清晰度和扩展性,提供高效灵活的操作接口。通过掌握命令模式的原则,开发者能够设计出更加灵活、可维护的代码结构,带来更快速的迭代开发体验。
没有回复内容