设计模式:备忘录模式(Memento)

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

备忘录模式的角色:
1. 原发器(Originator):负责创建一个备忘录,用以记录当前对象的内部状态,通过也可以使用它来利用备忘录回复内部状态。同时原发器还可以根据需要决定Memento存储Originator的那些内部状态。
2. 备忘录(Memento):用于存储Originator的内部状态,并且可以防止Originator以外的对象访问Memento。在备忘录Memento中有两个接口,其中Caretaker只能看到备忘录中的窄接口,它只能将备忘录传递给其他对象。Originator可以看到宽接口,允许它访问返回到先前状态的所有数据。
3. 负责人(Caretaker):负责保存好备忘录,不能对备忘录的内容进行操作和访问,只能够将备忘录传递给其他对象。

典型的备忘录代码:

public class Memento
{
    private String state;
    public Memento(Oraginator o)
    {
        state = o.state;
    }

    public void setState(String state){
        this.state = state;
    }

    public String getState()
    {
        return this.state;
    }
}

案例

大家一般都玩过游戏吧,就算没玩过游戏也见过室友、朋友玩过游戏吧。很多游戏中需要存档,保存当前的血条和魔法值,以防再挑战boss的时候die了可以重新读档。
1 原发器Originator

public class Originator
{
    private int bloodValue;
    private int magicValue;

    public Originator(int bloodValue, int magicValue){
        this.bloodValue = bloodValue;
        this.magicValue = magicValue;
    }

    public int getBloodValue()
    {
        return bloodValue;
    }

    public void setBloodValue(int bloodValue)
    {
        this.bloodValue = bloodValue;
    }

    public int getMagicValue()
    {
        return magicValue;
    }

    public void setMagicValue(int magicValue)
    {
        this.magicValue = magicValue;
    }

    public void display()
    {
        System.out.println("用户当前状态:");
        System.out.println("血量:"+getBloodValue()+";蓝量:"+getMagicValue());
    }

    public Memento saveMemento()
    {
        return new Memento(getBloodValue(),getMagicValue());
    }

    public void restoreMemento(Memento memento){
        this.bloodValue = memento.getBloodValue();
        this.magicValue = memento.getMagicValue();
    }
}

2 备忘录Memento

public class Memento
{
    private int bloodValue;
    private int magicValue;

    public int getBloodValue()
    {
        return bloodValue;
    }

    public void setBloodValue(int bloodValue)
    {
        this.bloodValue = bloodValue;
    }

    public int getMagicValue()
    {
        return magicValue;
    }

    public void setMagicValue(int magicValue)
    {
        this.magicValue = magicValue;
    }

    public Memento(int bloodValue, int magicValue)
    {
        this.bloodValue = bloodValue;
        this.magicValue = magicValue;
    }
}

3 负责人Caretaker

public class Caretaker
{
    private Memento memento;

    public Memento getMemento()
    {
        return memento;
    }

    public void setMemento(Memento memento)
    {
        this.memento = memento;
    }
}

4 测试代码

        Originator originator = new Originator(100,100);
        System.out.println("Before fighting BOSS...");
        originator.display();

        //存档
        Caretaker caretaker = new Caretaker();
        caretaker.setMemento(originator.saveMemento());

        //Fighting
        System.out.println("Fighting...");
        originator.setBloodValue(20);
        originator.setMagicValue(20);
        originator.display();

        //回复存档
        System.out.println("Restore...");
        originator.restoreMemento(caretaker.getMemento());
        originator.display();

输出结果:

Before fighting BOSS...
用户当前状态:
血量:100;蓝量:100
Fighting...
用户当前状态:
血量:20;蓝量:20
Restore...
用户当前状态:
血量:100;蓝量:100

在备忘录模式中,最重要的就是备忘录Memento了。备忘录中存储的就是原发器的部分或者所有的状态信息,而这些状态信息是不能够被其它对象所访问的,也就是说我们是不可能在备忘录之外的对象来存储这些状态信息,如果暴漏了内部状态信息就违反了封装的原则,故备忘录是处理原发器外其它对象都是不可以访问的。

优缺点
优点:
1. 给用户提供了一种可以恢复状态的机制。可以是用户能够比较方便地回到某个历史的状态。
2. 实现了信息的封装。使得用户不需要关心状态的保存细节。
缺点:
1. 消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。

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

JDK中的备忘录模式:
java.util.Date(Date对象通过自身内部的一个long值来实现备忘录模式)
java.io.Serializable

参考资料
1. 23种设计模式
2. 细数JDK里的设计模式
3. 设计模式读书笔记—–备忘录模式

时间: 2024-12-23 22:37:17

设计模式:备忘录模式(Memento)的相关文章

乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)

原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabcd 介绍 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到保存的状态. 示例 有一个Message实体类,某个对象对它的操作有Insert()方法,只有在插入时间符合要求的情况下才能插入成功,因此要求可以保存和恢复Message对象的状态,插入失败

【设计模式】—— 备忘录模式Memento

模式意图 这个模式主要是想通过一个对象来记录对象的某种状态,这样有利于在其他需要的场合进行恢复. 该模式还有跟多可以扩展的地方,比如可以记录多个时间的状态,每个角色都有可以扩展的空间,完全看业务场景而定. 应用场景 1 保存对象某一时刻的状态 2 避免直接暴露接口,破坏封装性 模式结构 Originator 是备忘录的发起者,记录状态的对象 class Originator{ private String state; public Memento ceateMemento() { return

设计模式之禅之设计模式-备忘录模式

<一:备忘录模式的定义        --->备忘录模式(Memento Pattern)提供了一种弥补真实世界缺陷的方法,让"后悔药"在程序的世界中真实可行        --->在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.        --->通俗地说,备忘录模式就是一个对象的备份模式,提供了一种程序数据的备份方法 二:备忘录模式的角色 ● Originator发起人角色      

学习php设计模式 php实现备忘录模式(Memento)_php技巧

一.意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样可以在以后把该对象的状态恢复到之前保存的状态. 二.备忘录模式结构图 三.备忘录模式中主要角色1.备忘录(Memento)角色: 存储发起人(Originator)对象的内部状态,而发起人根据需要决定备忘录存储发起人的哪些内部状态. 备忘录可以保护其内容不被发起人(Originator)对象之外的任何对象所读取.2.发起人(Originator)角色:创建一个含有当前的内部状态的备忘录对象 使用备忘录对象存

.net设计模式实例之备忘录模式(Memento Pattern)

一.备忘录模式简介(Brief Introduction) 备忘录模式(Memento Pattern),在不破坏封装的前提下,捕获一个对象的内部状态, 并在该对象之外保存这个状态.这样以后就可以就该对象恢复到原先保存的状态. 二.解决的问题(What To Solve) 当系统功能比较复杂,而且需要记录历史属性以便当需要时做恢复动作.Originator可以 根据保存的Memento信息还原到前一状态. 三.备忘录模式分析(Analysis)1.备忘录模式结构 Originator类:发起人.

PHP设计模式——备忘录模式

声明:本系列博客参考资料<大话设计模式>,作者程杰.                 备忘录模式又叫做快照模式或Token模式,在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.              UML类图:                              角色:                 1.发起人(GameRole):负责创建一个备忘录,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.发

IOS设计模式-备忘录模式

内容大纲 如何存储记录 备忘录模式的基本原理 使用备忘录模式 优化存储方案 恢复UIView的状态 1.如何存储记录 在存储记录时,第一步我们需要用一把钥匙去打开一把锁.第二步,当我们打开锁之后就会有黑盒子,我们一开始还不知道里面有什么,所以是黑盒子. 1.存储记录的必要性 生活中,比如去超市购物有时候就需要在入口储物柜存放自己的包裹 2.记录的唯一标示 储物柜对应一把钥匙和号码标示. 3.存储记录与取出记录 ===========================================

Java设计模式--备忘录模式

备忘录模式(别名:标记) 在不破坏封装性的前提下,捕捉一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可将该对象恢复到原先保存的状态. Memento Pattern(Another Name: Token) Without violating encapsulation, capture and externalize an object original state so that the object can be restored to this state later. 类图

21、Python与设计模式--备忘录模式

一.游戏进度保存 打过游戏的朋友一定知道,大多数游戏都有保存进度的功能,如果一局游戏下来,忘保存了进度,那么下次只能从上次进度点开始重新打了.一般情况下,保存进度是要存在可持久化存储器上,本例中先以保存在内存中来模拟实现该场景的情形.以模拟一个战斗角色为例.首先,创建游戏角色. class GameCharacter(): vitality = 0 attack = 0 defense = 0 def displayState(self): print 'Current Values:' pri

c#设计模式-备忘录模式-备忘录对象被改变

问题描述 usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespacetest3{classChess{privateint[,]a=newint[10,10];publicChess(){for(inti=0;i<10;i++){for(intj=0;j<10;j++)a[i,j]=0;}}publicvoidsetChes