Java设计模式——备忘录模式(Memento)

又名快照模式或者token模式

备忘录对象是一个用来存储另一个对象内部状态的快照(snapshot)的对象。备忘录模式用意是在不破坏封装的条件下,将下一个对象的状态捕捉(capture),并外部化(externalize),存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。备忘录模式常常与命令模式和迭代子模式一起使用。

备忘录模式涉及的角色:备忘录角色、发起人角色、负责人角色

备忘录角色(Memento):

1、将发起人(Originator)对象的内部状态存储起来。备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态

2、备忘录可以保护其内容不被发起人对象之外的任何对象所读取。

两个等效的接口

窄接口:负责人(Caretaker)对象看到的备忘录的窄接口,这个窄接口只允许他把备忘录对象传给其他对象

宽接口:与负责人对象看到的窄接口相反的是,发起人可以可以看到一个宽接口,这个宽接口允许他读取所有数据,以便根据这些数据恢复发起人对象的内部状态。

发起人角色(Originator):

1、创建一个含有当前内部状态的备忘录对象

2、使用备忘录对象存储其内部状态

负责人角色(Caretaker):

1、负责保存备忘录对象

2、不检查备忘录对象的内容

一、备忘录模式的白箱实现

如下图所示,示意性的“白箱实现”

发起人利用新创建的备忘录对象将自己的内部状态存储起来,代码如下:

public class Originator {

 private String state;

 /**
  * 工厂方法,返还一个新的备忘录对象
  * factory method,return a new Memento Object
  * @author 付玉伟
  * @time 2015-5-9 下午07:10:13
  * @return
  */
 public Memento createMemento(){
  return new Memento();
 }

 /**
  * 将发起人恢复到备忘录对象所记载的状态
  * retrieve originator to status of storing in Memento
  * @author 付玉伟
  * @time 2015-5-9 下午07:11:45
  * @param memento
  */
 public void restoreMemento(Memento memento){
  this.state = memento.getState();
 }

 public String getState() {
  return state;
 }

 public void setState(String state) {
  this.state = state;
  System.out.println("current state is:"+this.state);
 }
}

下面是备忘录角色的源代码,备忘录对象将发起人对象传入状态存储起来。备忘录角色会根据发起人对象的判断类决定将发起人的内部状态的多少存储起来。

public class Memento {

 private String state;

 public Memento(String state){
  this.state = state;
 }

 public String getState() {
  return state;
 }

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

下面是负责人角色的源码

public class Caretaker {

 private Memento memento;

 /**
  * 备忘录的取值方法
  * get value of Memento
  * @author 付玉伟
  * @time 2015-5-9 下午07:21:34
  * @return
  */
 public Memento retrieveMemento(){
  return this.memento;
 }

 /**
  * 备忘录的赋值方法
  * set value of Memento
  * @author 付玉伟
  * @time 2015-5-9 下午07:22:41
  * @param memento
  */
 public void saveMemento(Memento memento){
  this.memento = memento;
 }
}

下面给出一个示意性的客户端代码:

public class Client {

 private static Originator o = new Originator();
 private static  Caretaker c = new Caretaker();

 public static void main(String[] args) {
  // change status of originator
  o.setState("On");
  // create Memento Object and save status Of originator
  c.saveMemento(o.createMemento());
  // change status of originator
  o.setState("Off");
  // retrieve status of originator
  o.restoreMemento(c.retrieveMemento());
 }
}

白箱实现的时序图:

系统运行的时序是这样的:

1、将发起人对象状态设置为on

2、调用发起人角色的createMemento方法,创建一个备忘录对象,将这个状态存储起来

3、将备忘录对象存储到负责人对象中

将发起人对象恢复到备忘录对象所记录的状态的时序图如下:

将发起人对象恢复备忘录对象所记录的状态系统运行的时序:

1、将发起人对象状态设置为off

2、将备忘录对象从负责人对象中取出来

3、将发起人对象恢复到备忘录对象所存储的状态,即on

白箱实现的优缺点:

优点:简单

缺点:破坏对发起人状态的封装

二、备忘录模式的黑箱实现

使用内部类实现黑箱模式的的类图如下:

在Originator类中 定义了一个内部的Memento类,由于Memento类的全部接口都是私有的,因此只有他自己和发起人可以调用。负责人角色Caretaker类的源代码可以看到,负责人角色能够得到备忘录对象是以MementoIF为接口的,由于这个接口仅仅是一个标识接口,因此负责人角色不可能改变这个备忘录对象的内容。

源码如下:

public class Originator {
    private String state;

    public Originator(){}

    public MementoIF createMemento(){
        return new Memento(this.state);
    }

    /**
     * 将发起人恢复到备忘录记录的状态
     * @author 付玉伟
     * @time 2015-5-12 下午09:59:02
     * @param memento
     */
    public void resotreMemento(MementoIF memento){
        Memento aMemento = (Memento)memento;
        this.setState(aMemento.getState());
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
protected class Memento implements MementoIF{
        private String savedState;

        Memento(String someState){
            this.savedState = someState;
        }
        public String getState() {
            return savedState;
        }
        public void setState(String someState) {
            this.savedState = someState;
        }

    }

}
public class Caretaker {
    private MementoIF memento;

    /**
     * 备忘录的取值方法
     * @author 付玉伟
     * @time 2015-5-12 下午10:04:51
     * @return
     */
    public MementoIF retrieveMemento(){
        return this.memento;
    }

    /**
     * 备忘录的赋值方法
     * @author 付玉伟
     * @time 2015-5-12 下午10:05:25
     * @param memento
     */
    public void saveMemento(MementoIF memento){
        this.memento = memento;
    }

}
public interface MementoIF {
}
public class Client {
    /**
     * @author 付玉伟
     * @time 2015-5-12 下午10:05:49
     * @param args
     */
    public static void main(String[] args) {
        Originator o = new Originator();
        Caretaker c = new Caretaker();
        // 改变负责人状态
        o.setState("on");
        // 创建备忘录对象,并将发起人状态存储起来
        c.saveMemento(o.createMemento());
        // 修改发起人对象的状态
        o.setState("off");
        // 恢复发起人的状态
        o.resotreMemento(c.retrieveMemento());
        System.out.println(o.getState());
    }
}

备忘录模式的应用

1、JDBC与数据库

在架构设计的时候都必须注意将商业逻辑与存储逻辑分割开来原因如下:

a.两者分开可以交给不同的设计师,便于系统维护

b.商业逻辑变化存储逻辑不一定变

c.存储逻辑变化商业逻辑不一定变

2、J2EE框架中备忘录模式的应用

Cookie、URL改写、HTML的隐藏表等

3、系统配置文件

时间: 2024-08-05 20:41:23

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

JAVA 设计模式 备忘录模式

用途 备忘录模式 (Memento) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 备忘录模式是一种行为型模式. 结构 图-备忘录模式结构图 Memento : 负责存储 Originator 对象的内部状态,并可以防止 Originator 以外的其他对象访问 Memento.Memento 有两个接口,Caretaker 只能看到备忘录的窄接口,它只能将备忘录传递给其他对象.Originator 可以看到一个宽接口,允

[工作中的设计模式]备忘录模式memento

一.模式解析 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捕捉(Capture)住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态.备忘录模式常常与命令模式和迭代子模式一同使用. 备忘录模式可以根据客户指令,将相应的对象特有属性进行快照,如果客户要恢复对象,则根据快照提供的特有属性进行还原. 二.模式代码 package memento.patten; /** *备忘录类,同时指定要保存的对象属性

[设计模式] 备忘录模式Memento Pattern

在GOF的<设计模式:可复用面向对象软件的基础>一书中对备忘录模式是这样说的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 类图和实例: 简单的模式实例: #include <iostream> #include <string> using namespace std; class Memento { private:     string state; public:     Memento(

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

备忘录模式存在的意义在于在程序里面我们可能会遇到撤销操作的问题,将对象恢复到某个状态.类似事务的回滚. 备忘录模式主要有三个对象 发起人(Originator):要备份的成员,它提供一个创建备忘录的方法,将自身的信息复制到备忘录中,并提供另一个方法将备忘录中信息覆盖自身信息. 备忘录(Memento):备忘录对象中包含存储发起人状态的成员变量,它提供set,get或构造方法保存发起人状态及获取发起人状态. 管理角色(Caretaker):用于管理备忘录对象的实现类. 发起人 package me

设计模式(行为型)之备忘录模式(Memento Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之中介者模式(Mediator Pattern)>http://blog.csdn.net/yanbober/article/details/45533335 概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无

深入浅出设计模式——备忘录模式(Memento Pattern)

模式动机 为了使软件的使用更加人性化,对于误操作,我们需要提供一种类似“后悔药”的机制,让软件系统可以回到误操作前的状态,因此需要保存用户每一次操作时系统的状态,一旦出现误操作,可以把存储的历史状态取出即可回到之前的状态.现在大多数软件都有撤销(Undo)的功能,快捷键一般都是Ctrl+Z,目的就是为了解决这个后悔的问题. 在应用软件的开发过程中,很多时候我们都需要记录一个对象的内部状态.在具体实现过程中,为了允许用户取消不确定的操作或从错误中恢复过来,需要实现备份点和撤销机制,而要实现这些机制

设计模式之备忘录模式(Memento)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

设计模式入门之备忘录模式Memento

//备忘录模式定义: //在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态. //这样以后就可以将该对象恢复到原先保存的状态 //实例:测试两种方案,两种方案在第一阶段的过程是相同的,第二阶段是不同的 //实例代码 //备忘录对象的窄接口 public interface FlowAMockMemento { //空的,所谓窄接口,即只是一个标识作用,它的持有者不可以调用任何它的方法 } //测试流程类 public class FlowAMock { private

【C#设计模式-备忘录模式】

一.备忘录模式的定义: 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 二.备忘录模式的结构和角色: 1.Originator(发起人):负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态.Originator可以根据需要决定Memento存储自己的哪些内部状态. 2.Memento(备忘录):负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问