17 备忘录(Memento)模式

备忘录模式

1.1 分类

(对象)行为型

1.2 提出问题

实现一个游戏的存档功能。希望在保存状态的同时可以不破坏类的封装。

1.3 解决方案

在不破坏封装性的前提下,捕获一个对象的内部状态。并在该对象之外保留这个状态。这样以后就可将该对象恢复到原先保存的状态。

1.4 实现类图

在这里插入图片描述

  1. 原发器(Originator)类可以生成自身状态的快照,也可以在需要时通过快照恢复自身状态。
  2. 备忘录 (Memento) 是原发器状态快照的值对象 (value object)。通常做法是将备忘录设为不可变的,并通过构造函数一次性传递数据。
  3. 负责人(Caretaker)仅知道“何时”和“为何”捕捉原发器的状态,以及何时恢复状态。
  4. 可以通过友元,使得Memonto中的状态只能被Originator方法。

1.5 示例代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <vector>
#include <ctime>
#include <string>

//Memento
class Memento {
    friend class Hero;
private:
    unsigned int m_state;
    std::string m_date;//metadata
public:
    Memento(unsigned int state) : m_state(state) {
        std::time_t now= std::time(0);
        m_date = std::ctime(&now);
    }
    std::string getDate() {
        return m_date;
    }
};

//Originator
class Hero {
private:
    unsigned int m_state;
public:
    Hero(unsigned int state) : m_state(state) {
        std::cout << "英雄:我的初始状态为:" << m_state << "\n";
    }
    void fight() {
        std::cout << "英雄:啊!被砍了一刀。\n";
        m_state -= rand() % 20;
        std::cout << "英雄:当前状态变为:"<<m_state<<"\n";
    }
    Memento* save() {
        return new Memento(m_state);
    }
    void restore(Memento* memento) {
        m_state = memento->m_state;
        std::cout << "英雄:当前状态恢复为:" << m_state << "\n";
    }
};

//caretaker
class Caretaker {
private:
    Hero* m_hero;
    std::vector<Memento*> m_mementos;
public:
    Caretaker(Hero* hero) : m_hero(hero) {}
    ~Caretaker() {
        for (auto item : m_mementos) delete item;
    }
    void backup() {
        std::cout << "管理者:正在保存英雄状态...\n";
        m_mementos.push_back(m_hero->save());
    }
    void undo() {
        if (!m_mementos.size()) return;

        Memento* memento = m_mementos.back();
        m_mementos.pop_back();
        std::cout << "管理者:英雄状态恢复为" << memento->getDate() << "\n";
        m_hero->restore(memento);
        delete memento;
    }
};
int main()
{
    std::srand(static_cast<unsigned int>(std::time(NULL)));
    Hero* hero = new Hero(100);
    Caretaker* caretaker = new Caretaker(hero);
    caretaker->backup();
    hero->fight();
    caretaker->backup();
    hero->fight();
    caretaker->undo();

    delete hero;
    delete caretaker;
}

1.6 举个栗子

使用了命令模式与备忘录模式,可保存复杂文字编辑器的状态快照,并能在需要时从快照中恢复之前的状态。 命令(command)对象将作为负责人,它们会在执行与命令相关的操作前获取编辑器的备忘录。当用户试图撤销最近的命令时,编辑器可以使用保存在命令中的备忘录来将自身回滚到之前的状态。
在这里插入图片描述

1.7 总结

1.7.1 优点

  1. 可以在不破坏对象封装情况的前提下创建对象状态快照。
  2. 可以通过负责人维护原发器状态历史记录,简化原发器代码。

1.7.2 缺点

负责人必须完整跟踪原发器的生命周期,这样才能销毁弃用的备忘录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值