命令模式(Command Pattern)是一种行为设计模式,它将请求封装成一个对象,从而使得可以参数化客户端对象传递不同的请求,并且能够支持请求的排队、记录请求日志、撤销操作等。在命令模式中,请求发送者和请求接收者之间通过命令对象进行解耦,从而实现了请求发送者和请求接收者之间的松耦合。
下面是一个使用QT C++编写的简单命令模式示例,
代码演示:
#include <QCoreApplication>
#include <QDebug>
#include <QString>
// 命令接口 作为一个基类
class Command {
public:
virtual ~Command() {}
virtual void execute() = 0; // 执行
virtual void undo() = 0; // 撤销
};
// 具体命令类 继承命令接口类
class LightOnCommand : public Command {
public:
void execute() override {
qDebug() << "开灯";
}
void undo() override {
qDebug() << "撤销开灯";
}
};
class LightOffCommand : public Command {
public:
void execute() override {
qDebug() << "关灯";
}
void undo() override {
qDebug() << "撤销关灯";
}
};
// 命令调用者
class RemoteControl {
public:
// 可以接收命令基类对象指针
void setCommand(Command* command) {
m_command = command;
}
void pressButton() {
if (m_command) {
m_command->execute();
m_undoStack.push(m_command); // 将对象入栈
} else {
qDebug() << "无命令写入";
}
}
void undoButton() {
if (!m_undoStack.empty()) {
Command* lastCommand = m_undoStack.top(); // 取出栈顶部对象(最后一个加入容器的对象)
lastCommand->undo();
m_undoStack.pop(); // 删除顶部对象
} else {
qDebug() << "无撤销操作";
}
}
private:
Command* m_command; // 保存命令对象指针
std::stack<Command*> m_undoStack; // 栈容器,用于保存使用过命令的对象
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建命令调用者对象
RemoteControl remote;
// 创建两个不同的命令对象
LightOnCommand lightOnCmd;
LightOffCommand lightOffCmd;
// 将不同的命令对象传入 调用者对象 ,然后执行命令
remote.setCommand(&lightOnCmd);
remote.pressButton();
remote.setCommand(&lightOffCmd);
remote.pressButton();
remote.undoButton();
return a.exec();
}
优点:
松耦合:命令模式将请求发送者和请求接收者解耦,使得请求发送者无需知道请求接收者的具体实现,从而降低系统的耦合度。
可扩展性:通过添加新的命令类,可以轻松地扩展系统的功能,而无需修改现有的代码。
支持撤销和重做:由于命令对象封装了请求,可以轻松地实现请求的撤销和重做操作。
支持日志记录:可以通过保存命令对象的历史记录,实现日志记录功能,便于跟踪和调试。
缺点:
类爆炸:如果系统中有大量的命令类,可能会导致类的数量急剧增加,增加系统的复杂性。
增加代码量:引入命令模式会增加额外的类和对象,可能会增加代码量,使得代码变得更加复杂。
可能降低性能:由于命令模式需要创建额外的对象来封装请求,可能会导致一定程度上的性能损失。
总的来说,命令模式在需要将请求发送者和请求接收者解耦、支持撤销和重做、支持日志记录等场景下非常有用。在实际应用中,需要根据具体的需求和场景权衡其优缺点,选择合适的设计模式。