备忘录模式-对象行为模式

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

动机:

有时有必要记录一个对象的内部状态。为了允许用户取消不确定的操作或从错误中恢复过来,需要实现检查点和取消机制,而要实现这些机制,必须实现将状态信息保存在某处,这样能将对象恢复到它们先前的状态。但是对象通常封装了其部分或所有的状态信息,使得其状态不能被其他对象访问,也就不可能在该对象之外保存其状态。而暴露其内部状态又将违反封装的原则,有可能有损应用的可靠性和可扩展性。

一个备忘录是一个对象,它存储另一个对象在某个瞬间的内部状态,而后者称为成为备忘录(memento)的原发器(originator)。当需要设置原发器的检查点时,取消操作机制会想原发器请求一个备忘录。原发器用描述当前状态的信息初始化备忘录。只有原发器可以向备忘录中存取信息,备忘录对其他对象“不可见”

适用性:

在以下情况使用备忘录模式:

1 必须保存一个对象在某个时刻的(部分)状态,这样以后需要时才能恢复到先前的状态

2 如果一个用接口来让其它对象直接得到这些状态,将会暴露对象的实现喜街并破坏对象的封装性。

结构:

 


参与者:

Memento

1 备忘录存储原发器对象的内部状态。原发器根据需要决定备忘录存储原发器的哪些内部状态。

2 防止原发器以外的其他对象访问备忘录。备忘录实际上有两个接口,管理者(caretaker)只能看到备忘录的窄接口--只能将备忘录传递给其他对象。相反,原发器能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。理想的情况是只允许生成备忘录的那个原发器访问备忘录的内部状态。

Originator(原发器)

1 原发器创建一个备忘录,用以记录当前时刻它的内部状态;2 使用备忘录回复内部状态

Caretaker(负责人)

1 负责保存好备忘录 2 不能对备忘录的内容进行操作或检查。

协作:

管理器向原发器请求一个备忘录,保留一段时间后,将其送回给原发器.如下图:

 

//±¸Íü¼ģʽ

#include <iostream>
using namespace std;

class GameRole;
class RoleStateMemento
{
public:
    RoleStateMemento()
    {
    }
    
    RoleStateMemento(int v, int a, int d)
        : vit(v), atk(a), def(d)
    {
    }
    
    virtual ~RoleStateMemento()
    {}

private:

    friend class GameRole; 
    int vit;
    int atk;
    int def;
};
//ÓÎÏ·½ÇÉ«£¬Ï൱ÓÚOriginatorÀà 
class GameRole
{
public:
    GameRole(int v = 100, int a = 100, int d = 100) :
        vit(v), atk(a), def(d)
    {}
    
    //״̬ÏÔʾ 
    void StateDisplay()
    {
        cout << "½ÇÉ«µ±Ç°×´Ì¬£º" << endl;
        cout << "ÌåÁ¦£º" << vit << "¹¥»÷Á¦£º" 
             << atk << "·ÀÓùÁ¦£º" << def << endl; 
    } 
    
    //±£´æ½Çɫ״̬
    RoleStateMemento& SaveState()
    {
        return *(new RoleStateMemento(vit, atk, def));
    } 
    
    //»Ö¸´½Çɫ״̬
    void RecoveryState(RoleStateMemento& memento)
    {
        vit = memento.vit;
        atk = memento.atk;
        def = memento.def;
    } 
    //Óëboss´óÕ½Ö®ºó״̬ 
    void Fight()
    {
        vit = 0;
        atk = 0;
        def = 0;
    }
private:
    int vit;   //ÉúÃüÁ¦ 
    int atk;   //¹¥»÷Á¦ 
    int def;   //·ÀÓùÁ¦ 
}; 

//½Çɫ״̬¹ÜÀíÕß
class RoleStateCaretaker
{
public:
    RoleStateMemento& GetMemento()
    {
        return memento;
    }
    
    void SetMemento(RoleStateMemento& m)
    {
        memento = m;
    }
private:
    RoleStateMemento memento;
};

int main()
{
    //´óÕ½BossÇ°
    GameRole lixiaoyao;
    lixiaoyao.StateDisplay();
    
    //±£´æ½ø¶È
    RoleStateCaretaker stateAdmin; 
    stateAdmin.SetMemento(lixiaoyao.SaveState());
    
    //´óÕ½bossʱ£¬ËðºÄÑÏÖØ
    lixiaoyao.Fight();
    lixiaoyao.StateDisplay();
    
    //»Ö¸´Ö®Ç°×´Ì¬
    lixiaoyao.RecoveryState(stateAdmin.GetMemento()); 
    lixiaoyao.StateDisplay();
    
    system("pause");
    return 0;
}

 

有时管理者不会将备忘录返回给原发器,因为原发器可能不需要退到先前的状态.

备忘录是被动的,只有创建备忘录的原发器会对它的状态进行赋值和检索.

效果:

1 保持封装边界:适用备忘录可以避免暴露一些只应由原发起管理却又必须存储在原发器之外的信息。把可能很复杂的Originator内部信息对其他对象屏蔽起来,从而保持了封装边界。

2 简化了原发器:Originator负责保持客户请求过的内部状态版本。把所有存储管理任务交给了Originator,让客户管理它们请求的状态会简化Originator,使客户工作结束时无需通知原发器。

3 适用备忘录可能代价很高;

4 定义窄接口和宽借口:在一些语言中很难保证只有原发器可访问备忘录的状态。

5 维护备忘录的潜在代价

实现:

1 语言支持  备忘录有两个接口:一个为原发器所使用的宽接口,一个为其他对象所使用的窄接口。理想的实现语言应可支持两级的静态保护。在C++中,可将Originator作为Memento的一个友元,并使Memento宽接口为私有的。只有窄借口应该被声明为共有的。

2 存储增量式改变:如果备忘录的创建及返回的顺序是可预测的,备忘录可以仅存储原发器内部状态的增量改变,而不是它所影响的每个对象的完整状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
备忘录模式是一种行为型设计模式,它允许在不破坏封装性的前提下捕获对象的内部状态,并在对象之外保存这个状态,以便在以后的某个时候将其恢复到原先的状态。 备忘录模式由三个主要角色组成: 1. 发起人(Originator):负责创建一个备忘录,并记录和恢复自身的内部状态。 2. 备忘录(Memento):负责存储发起人对象的内部状态。 3. 管理者(Caretaker):负责保存备忘录,并可以对其进行管理,但不知道备忘录的具体内容。 该模式的工作流程如下: 1. 发起人创建一个备忘录,将自己的状态保存在备忘录。 2. 发起人可以根据需要在任何时候保存自己的状态。 3. 管理者将备忘录保存起来,可维护多个备忘录。 4. 在需要恢复状态的时候,可以通过管理者获取相应的备忘录,并将发起人的状态恢复到备忘录保存的状态。 备忘录模式的优点是: - 发起人对象与备忘录对象分离,实现了信息的封装和隐藏。 - 备忘录对象存储了发起人对象的历史状态,可以实现撤销和恢复操作。 - 备忘录可以进行存储和管理,可进行序列化和持久化操作。 备忘录模式通常适用于以下情况: - 需要保存和恢复对象的状态,并且封装对象的状态对于其他对象来说是不可见的。 - 需要实现撤销和恢复功能。 - 需要保存和恢复部分或全部对象状态的场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值