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类就可以了。

相关推荐
float_六七1 小时前
Java——单例类设计模式
java·单例模式·设计模式
老菜鸟的每一天1 小时前
创建型模式-Prototype 模式(原型模式)
设计模式·原型模式
码熔burning2 小时前
(五)趣学设计模式 之 建造者模式!
java·设计模式·建造者模式
黑不溜秋的10 小时前
C++ 设计模式 - 策略模式
c++·设计模式·策略模式
付聪121012 小时前
策略模式介绍和代码示例
设计模式
ThereIsNoCode13 小时前
「软件设计模式」状态模式(State)
设计模式·状态模式
小猫猫猫◍˃ᵕ˂◍15 小时前
备忘录模式:快速恢复原始数据
android·java·备忘录模式
菜鸟一枚在这19 小时前
深入理解设计模式之代理模式
java·设计模式·代理模式
mjr21 小时前
设计模式-Java
java·设计模式
yuanpan21 小时前
23种设计模式之《组合模式(Composite)》在c#中的应用及理解
开发语言·设计模式·c#·组合模式