QT设计模式:备忘录模式

**备忘录模式(Memento Pattern)**是一种行为型设计模式,主要用于保存一个对象当前的状态,并在需要时恢复该状态。它常应用于以下场景:

  1. 撤销操作:如文本编辑器撤销、软件开发中的版本控制等,用户可以返回到之前的状态。
  2. 备份和恢复:系统故障时,使用备份数据恢复到之前的状态,减少数据丢失风险。
  3. 系统快照:在执行高风险操作之前,创建系统状态的快照,方便后续进行回滚操作。

备忘录模式主要有三个参与者:发起人(Originator)、备忘录(Memento)和负责人(Caretaker)。发起人负责创建备忘录和恢复状态;备忘录负责存储发起人的状态信息;负责人管理多个备忘录。

QT示例:

Memento:增加一个Memento类去记录QTextEdit的字体和颜色;

MyCommand类:对应备忘录模式的Originator(发起人);

QUndoStack类:对应 Caretaker(负责人),负责管理撤销和重做操作,维护命令的历史记录。

复制代码
#include <QApplication>
#include <QTextEdit>
#include <QUndoStack>
#include <QPushButton>
#include <QVBoxLayout>
#include <QUndoCommand>

class Memento {
public:
    Memento(const QString &text, const QFont &font, const QColor &color)
        : m_text(text), m_font(font), m_color(color) {}

    const QString& getText() const { return m_text; }
    const QFont& getFont() const { return m_font; }
    const QColor& getColor() const { return m_color; }

private:
    QString m_text;
    QFont m_font;
    QColor m_color;
};

class QUndoCommand
{
public:
    virtual ~QUndoCommand() {}
    virtual void undo() = 0;
    virtual void redo() = 0;
};

class MyCommand : public QUndoCommand {
public:
    MyCommand(QTextEdit *editor, const QString &text, const QFont &font, 
              const QColor &color, QUndoCommand *parent = nullptr)
        : QUndoCommand(parent), m_editor(editor),
          m_newMemento(std::make_shared<Memento>(text, font, color)) {

        m_oldMemento = std::make_shared<Memento>(editor->toPlainText(), 
                                                 editor->font(), editor->textColor());
    }

    void undo() override {
        m_editor->setPlainText(m_oldMemento->getText());
        m_editor->setFont(m_oldMemento->getFont());
        m_editor->setTextColor(m_oldMemento->getColor());
    }

    void redo() override {
        m_editor->setPlainText(m_newMemento->getText());
        m_editor->setFont(m_newMemento->getFont());
        m_editor->setTextColor(m_newMemento->getColor());
    }

private:
    QTextEdit *m_editor;
    std::shared_ptr<Memento> m_newMemento;
    std::shared_ptr<Memento> m_oldMemento;
};

class QUndoStack
{
public:
    void push(QUndoCommand *cmd)
    {
        m_stack.push(cmd);
        cmd->redo();
    }

    void undo()
    {
        if (!m_stack.isEmpty()) {
            QUndoCommand *cmd = m_stack.pop();
            cmd->undo();
            m_undoStack.push(cmd);
        }
    }

    void redo()
    {
        if (!m_undoStack.isEmpty()) {
            QUndoCommand *cmd = m_undoStack.pop();
            cmd->redo();
            m_stack.push(cmd);
        }
    }

private:
    QStack<QUndoCommand*> m_stack;
    QStack<QUndoCommand*> m_undoStack;
};

int main(int argc, char **argv) {
    QApplication app(argc, argv);

    QUndoStack stack;

    QTextEdit editor;
    QPushButton undoButton("Undo");
    QPushButton redoButton("Redo");

    QObject::connect(&undoButton, &QPushButton::clicked, &stack, &QUndoStack::undo);
    QObject::connect(&redoButton, &QPushButton::clicked, &stack, &QUndoStack::redo);

    // 假设用户通过一些方式,可以更改QTextEdit的字体和颜色
    QObject::connect(&editor, &QTextEdit::cursorPositionChanged, [&]() {
        QFont font = editor->font();
        QColor color = editor->textColor();
        stack.push(new MyCommand(&editor, editor.toPlainText(), font, color));
    });

    QVBoxLayout layout;
    layout.addWidget(&editor);
    layout.addWidget(&undoButton);
    layout.addWidget(&redoButton);

    QWidget window;
    window.setLayout(&layout);
    window.show();

    return app.exec();
}

在这个示例中,我们假设用户可以通过一些方式,可以更改QTextEdit的字体和颜色,并且这也需要做到撤销和重做。我们如果结合使用备忘录模式,增加一个Memento类去记录QTextEdit的字体和颜色,那么这个过程就简单的多了。否则,MyCommand类需要存储所有的状态,如果状态相关的数据对象越来越多,可能会导致MyCommand类的职责过重。

在这里,MyCommand类兼任了备忘录模式的Originator类和命令模式的Receiver类,QUndoStack类兼任了备忘录模式的Caretaker类和命令模式的Invoker类。所以实际上,命令模式和备忘录模式,可以简单理解为在命令模式的基础上增加一个Memento类就可以了。

相关推荐
老蒋每日coding3 小时前
AI Agent 设计模式系列(十九)—— 评估和监控模式
人工智能·设计模式
会员果汁4 小时前
23.设计模式-解释器模式
设计模式·解释器模式
「QT(C++)开发工程师」11 小时前
C++设计模式
开发语言·c++·设计模式
茶本无香12 小时前
设计模式之七—装饰模式(Decorator Pattern)
java·设计模式·装饰器模式
漂洋过海的鱼儿1 天前
设计模式——EIT构型(三)
java·网络·设计模式
老蒋每日coding1 天前
AI Agent 设计模式系列(十八)—— 安全模式
人工智能·安全·设计模式
老蒋每日coding1 天前
AI Agent 设计模式系列(十六)—— 资源感知优化设计模式
人工智能·设计模式·langchain
老蒋每日coding1 天前
AI Agent 设计模式系列(十七)—— 推理设计模式
人工智能·设计模式
冷崖1 天前
桥模式-结构型
c++·设计模式
连山齐名1 天前
设计模式之一——堵塞队列
设计模式