基本概念
命令模式(Command Pattern)是一种行为设计模式,它通过将请求封装为具有公共接口的对象,从而允许将请求参数化、队列化、保存和执行。
使用场景
- 当需要将请求发送者与请求接收者解耦的场景
- 当需要将操作进行排队的场景
- 当操作需要支持撤销的场景
- 当要对操作过程记录日志的场景
- 当操作需要支持事务操作的场景
实现的类
- Command类:是一个接口,定义了执行操作和撤销操作的方法。
- ConcreteCommand类:具体的执行命令,他们需要实现Command接口,负责执行具体的操作。
- Invoker类:发送命令的对象。它并不知道具体的命令实现细节,只是将命令对象发送给接收者来执行。
- Receiver类:真正执行命令的角色,那些具体的命令引用它,让它完成命令的执行。
实现:QT文本编辑器
Command类
// 命令接口
class Command : public QUndoCommand
{
public:
explicit Command(QTextEdit *editor) : m_editor(editor) {}
virtual void execute() = 0;
protected:
QTextEdit *m_editor;
};
Command
类是一个抽象类,继承自 QUndoCommand
,定义了执行操作的接口方法 execute()
。它提供了一个统一的接口,用于执行具体的操作。
ConcreteCommand类
// 具体的执行命令
class ConcreteCommand : public Command
{
public:
ConcreteCommand(QTextEdit *editor, const QString &text)
: Command(editor), m_text(text) {}
//执行数据插入
void execute() override
{
m_editor->textCursor().insertText(m_text);
}
private:
QString m_text;
};
ConcreteCommand
类继承自 Command
类,负责具体的操作逻辑。在这个例子中,ConcreteCommand
类的任务是在文本编辑器中插入指定的文本。
Receiver类
// 文本编辑器接收者
class Receiver : public QObject
{
Q_OBJECT
public:
Receiver(QTextEdit *editor) : m_editor(editor) {}
public slots:
void insertText(const QString &text)
{
m_editor->textCursor().insertText(text);
}
private:
QTextEdit *m_editor;
};
Receiver
类其中包含了一个槽函数 insertText
,负责在文本编辑器中插入文本。Receiver
类接收并执行命令,实际执行操作的地方。
Invoker实现(QUndoStack)
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 创建文本编辑器窗口
QTextEdit textEdit;
textEdit.setWindowTitle("Simple Text Editor");
textEdit.show();
// 创建撤销栈
QUndoStack undoStack;
// 创建文本编辑器接收者对象
Receiver receiver(&textEdit);
// 创建调用者对象并将其与撤销栈和接收者关联
QUndoCommand *insertCommand = new ConcreteCommand(&textEdit, "Hello, World!");
undoStack.push(insertCommand);
// 执行命令
undoStack.undo(); // 撤销插入操作
return app.exec();
}
在 main 函数中,我们创建了一个 QUndoStack
对象 undoStack
,它充当了调用者的角色。QUndoStack
类提供了管理命令的功能,包括执行和撤销命令。我们将具体的命令对象添加到 undoStack
中,并调用 undo()
方法执行命令。因此,undoStack
是命令模式中的调用者,负责调度命令的执行和撤销。