wq-7047

视频链接:

https://www.bilibili.com/video/BV1ZK411V7gS/

1定义

备忘录模式(Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

 

备忘录模式结构图

Originator (发起人):负责创建一个备忘录Memento, 用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。Originator 可根据需要决定Memento存储Originator的哪些内部状态。

Memento (备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录Memento。备忘录有两个接口,Caretaker 只能看到备忘录的窄接口,它只能将备忘录传递给其他对象。Originator 能够看到一个宽接口,允许它访问返回到先前状态所需的所有数据。

Caretaker (管理者):负责保存好备忘录Memento,不能对备忘录的内容进行操作或检查。

2意义与作用

备忘录模式基本代码:

发起人(Originator) 类

class Originator
{
    private string state;
    public string State
    {
        get{ return state; }
        get{ state = value; }
    }
    public Memento CreateMemento ()
    {
        return (new Memento (state)) ;
    }
    public void SetMemento (Memento memento)
    {
        state = memento.State;
    }
    public void Show ()
    {
        Console. WriteLine ("State=” + state) ;
    }
}

 

备忘录(Memento)类

class Memento
{
    private string state;
    public Memento (string state)
    {
        this.state = state;
    }
    public string State
    {
        get { return state; }
    }
} 

 

管理者(Caretaker) 类

class Caretaker
{
    private Memento memento;
    public Memento Memento
    {
        get{ return memento;}
        set { memento = value;}
    }
}

 

客户端程序

static void Main(string[] args)
{
    Originator  o= new Originator();
    o.State = "On";
    o.Show();

    Caretaker  c = new Caretaker() ;
    c.Memento = o. Creat eMemento() ;

    o.State = "Off";
    o.Show();
    o. SetMemento (c.Memento) ;
    o.Show() ;

    Console.Read() ;
}

 

在备忘录模式中,把要保存的细节给封装在了Memento中了,如果要更改保存的细节也不会影响客户端。

Memento模式比较适用于功能比较复杂的,但需要维护或记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时, Originator可以根据保存的Memento信息还原到前一状态。

如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。有时一些对象的内部信息必须保存在对象以外的地方,但是必须要由对象自己读取,这时,使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。

备忘录模式最大的作用还是在当角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。

所以总结下来就是:

1. 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
2. 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

3应用场景

备忘录模式被使用于以下的情况:

  1. 需要保存一个对象在某一个时刻的状态或部分状态。
  2. 如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访问其内部状态。

所以备忘录模式经常可以遇到,譬如下面这些场景:

  • 浏览器回退:浏览器一般有浏览记录,当我们在一个网页上点击几次链接之后,可在左上角点击左箭头回退到上一次的页面,然后也可以点击右箭头重新回到当前页面
  • 数据库备份与还原:一般的数据库都支持备份与还原操作,备份即将当前已有的数据或者记录保留,还原即将已经保留的数据恢复到对应的表中。
  •  编辑器撤销与重做:在编辑器上编辑文字,写错时可以按快捷键 Ctrl + z 撤销,撤销后可以按 Ctrl + y 重做。
  • 虚拟机生成快照与恢复:虚拟机可以生成一个快照,当虚拟机发生错误时可以恢复到快照的样子。
  • Git版本管理:Git是最常见的版本管理软件,每提交一个新版本,实际上Git就会把它们自动串成一条时间线,每个版本都有一个版本号,使用 git reset --hard 版本号 即可回到指定的版本,让代码时空穿梭回到过去某个历史时刻。
  • 棋牌游戏悔棋:在棋牌游戏中,有时下快了可以悔棋,回退到上一步重新下。

4实例实现

游戏进度备忘录结构图

游戏角色类:1. 新增“保存角色状态”方法,将游戏角色的三个状态值通过实例化“角色状态存储箱”返回。2. 新增“恢复角色状态”方法,可将外部的“角色状态存储箱”中状态值恢复给游戏角色。

class 游戏角色
{
    ……
    //保存角色状态
    public RoleStateMemento  SaveState ()
    {
        return (new RoleStateMemento(vit, atk, def) ) ;
    }
    //恢复角色状态
    public void RecoveryState (RoleStateMemento memento)
    {
        this.vit = memento. Vitality;
        this.atk = memento. Attack;
        this.def = memento. Defense;
    }
    ……
}

 

角色状态存储箱类:将生命力、攻击力、防御力存入状态存储箱对象中。

//角色状态存储箱
class RoleStateMemento
{
    private int vit;
    private int atk;
    private int def;
    public RoleStateMemento(int vit, int atk, int def)
    {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }
    //生命力
    public int Vitality
    {
        get { return vit; }
        set { vit = value; }
    }
    //攻击力
    public int Attack
    {
        get { return atk;}
        set{ atk = value;}
    }
    //防御力
    public int Defense
    {
        get { return def; }
        set { def = value; }
    }
}

 

角色状态管理者类

//角色状态管理者
class RoleStateCaretaker
{
    private RoleStateMemento  memento ;
    public RoleStateMemento Memento
    {
        get{ return memento;}
        set { memento = value;}
    }
}

 

客户端代码:1. 游戏角色初始状态,三项指标数据都是100。2. 保存进度时,由于封装在Memento中,因此我们并不知道保存了哪些具体的角色数据。

static void Main(string[] args)
{
    //大战Boss之前
    GameRole lixiaoyao = new GameRole() ;
    lixiaoyao.GetInitState() ;
    lixiaoyao.StateDisplay() ;

    //保存进度
    RoleStateCaretaker  stateAdmin = new RoleStateCaretaker () ;
    stateAdmin. Memento = lixiaoyao.SaveState() ;  
 
    //大战Boss时,损耗严重
    lixiaoyao.Fight() ;
    lixiaoyao.StateDisplay() ;

    //恢复之前状态
    Lixiaoyao.RecoveryState (stateAdmin . Memento) ;
    lixiaoyao.StateDisplay() ;  

    Console.Read() ;
}

5总结

备忘录模式是一种对象行为型模式,其主要优点如下:

  1. 提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
  2. 实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
  3. 简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。

其主要缺点是:资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。

参考链接:

https://blog.csdn.net/wwwdc1012/article/details/83353580

https://www.jianshu.com/p/14d27c8fea8d

 

分类:

技术点:

相关文章:

  • 2021-11-20
  • 2022-01-11
  • 2021-05-19
  • 2022-02-19
  • 2021-04-29
  • 2021-07-12
  • 2021-09-07
  • 2021-08-20
猜你喜欢
  • 2021-11-30
  • 2021-12-27
  • 2021-06-14
  • 2021-08-28
  • 2022-01-03
  • 2022-02-06
相关资源
相似解决方案