概念:

  Memento模式也叫备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是GoF的23种设计模式之一,属于行为模式,它的作用是保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。

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

  备忘录模式的结构

  备忘录模式的角色和职责

  1、Originator(原生者):需要被保存状态以便恢复的那个对象,负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。

  2、Memento(备忘录):该对象由Originator创建,主要负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状

态所需要的所有数据。

  3、Caretaker(管理者):负责在适当的时间保存/恢复Originator对象的状态,负责备忘录Memento,不能对Memento的内容进行访问或者操作。

  备忘录模式的应用场景

  如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。

  (1)一个类需要保存它的对象的状态(相当于Originator角色)
  (2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色)
  (3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存
  (4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态

  下面用代码来实现一下

  首先,新建一个Person类,他就是Originator(原生者)

 /*
* Originator(原生者)
*/
public class Person {
/*
* 姓名,年龄,性别就是结构图中的state,状态属性
*/
//姓名
private String name;
//年龄
private int age;
//性别
private String sex; public Person() {
super();
} public Person(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
} public void display() {
System.out.println("name:" + name + ",sex:" + sex + ",age:" + age);
} //创建一个备份
public Memento createMemento(){
return new Memento(name,age,sex);
} //恢复一个备份
public void setMemento(Memento memento){
this.name = memento.getName();
this.age = memento.getAge();
this.sex = memento.getSex();
}
}

  接着,创建一个Memento(备忘录),他和Originator的基本结构是一样的

 /*
* Memento(备忘录)
*/
public class Memento {
//姓名
private String name;
//年龄
private int age;
//性别
private String sex; public Memento() {
super();
} public Memento(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getSex() {
return sex;
} public void setSex(String sex) {
this.sex = sex;
}
}

  接下来,创建客户端运行一下

 public class MainClass {
public static void main(String[] args) {
Person person = new Person("小明",18,"男");
//打印
person.display(); //创建一个备份
Memento memento = person.createMemento(); person.setName("小红");
person.setAge(17);
person.setSex("女");
//打印
person.display(); //备份还原
person.setMemento(memento);
//打印
person.display();
}
}

  结果:

  这样,就做到了一个备份还原的过程,但是可以看到,根据结构图看,我们还缺少了一个Caretaker(管理者)角色

  这个角色的作用其实就是把备份还原的过程交到管理者手中,通过管理者来备份还原

 /*
* Caretaker(管理者)
*/
public class Caretaker {
//持有一个对Memento的引用
private Memento memento; public Memento getMemento() {
return memento;
} public void setMemento(Memento memento) {
this.memento = memento;
}
}

  客户端

 public class MainClass {
public static void main(String[] args) {
Person person = new Person("小明",18,"男");
//打印
person.display(); //创建一个管理者
Caretaker caretaker = new Caretaker(); //创建一个备份
// Memento memento = person.createMemento();
caretaker.setMemento(person.createMemento()); person.setName("小红");
person.setAge(17);
person.setSex("女");
//打印
person.display(); //备份还原
person.setMemento(caretaker.getMemento());
//打印
person.display();
}
}

  运行结果是一样的

  备忘录模式的优点和缺点

  一、备忘录模式的优点
    1、有时一些发起人对象的内部信息必须保存在发起人对象以外的地方,但是必须要由发起人对象自己读取,这时,使用备忘录模式可以把复杂的发起人内部信息对其他的对象屏蔽起来,从而可以恰当地保持封装的边界。
    2、本模式简化了发起人类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可以自行管理他们所需要的这些状态的版本。
    3、当发起人角色的状态改变的时候,有可能这个状态无效,这时候就可以使用暂时存储起来的备忘录将状态复原。
  二、备忘录模式的缺点:
    1、如果发起人角色的状态需要完整地存储到备忘录对象中,那么在资源消耗上面备忘录对象会很昂贵。
    2、当负责人角色将一个备忘录存储起来的时候,负责人可能并不知道这个状态会占用多大的存储空间,从而无法提醒用户一个操作是否很昂贵。
    3、当发起人角色的状态改变的时候,有可能这个协议无效。如果状态改变的成功率不高的话,不如采取“假如”协议模式。

java设计模式-----21、备忘录模式的更多相关文章

  1. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  2. java设计模式之备忘录模式

    备忘录模式 备忘录模式是一种软件设计模式:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态.一听到备忘录这个字的时候想起了小小时打的游 ...

  3. java设计模式9.备忘录模式、访问者模式、调停者模式

    备忘录模式 备忘录模式又叫快照模式,备忘录对象是一个用来存储另外一个对象内部状态快照的对象.备忘录的用意是在不破坏封装的条件下,将一个对象的状态捕捉,并外部化存储起来,从而可以在将来合适的时候把这个对 ...

  4. Java设计模式应用——备忘录模式

    备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2 ...

  5. 19.java设计模式之备忘录模式

    基本需求 游戏的角色有攻击力和防御力,在大战Boss之前保存自身的状态(攻击力和防御力),当大战Boss之后攻击力和防御力下降,从备忘录对象恢复到大战前的状态 传统方案 一个对象,就对应一个保存对象状 ...

  6. 观世音甘泉活树的故事竟然是Java设计模式:备忘录模式

    目录 定义 意图 主要解决问题 何时使用 优缺点 结构 白箱实现 黑箱实现 多重检查点 观世音甘泉活树的故事 定义 备忘录模式是对象的行为型模式,备忘录对象是一个用来存储另外一个对象内部状态的快照的对 ...

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

    原文:乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 备忘录模式(Memento Pattern) 作者:webabc ...

  8. Java设计模式——装饰者模式

    JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...

  9. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  10. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

随机推荐

  1. 【BZOJ3193】 [JLOI2013]地形生成

    BZOJ3193 [JLOI2013]地形生成 Solution 第一问不是很简单吗? 直接计数就好了. 第二问思考无果看了看hyj神仙的代码,发现可以dp求解. 具体可以看代码(其实主要是我说不清楚 ...

  2. Python3.5学习十八 Python之Web框架 Django

    Python之Web框架: 本质:Socket 引用wsgiref创建web框架 根据web框架创建过程优化所得: 分目录管理 模板单独目录 执行不同函数单独存入一个方法py文件 Web框架的两种形式 ...

  3. C语言通过匿名管道实现反弹式CMDShell

    #pragma comment(lib,"ws2_32.lib") #ifdef _MSC_VER #pragma comment( linker, "/subsyste ...

  4. 【learning】 扩展欧几里得算法(扩展gcd)和乘法逆元

    有这样的问题: 给你两个整数数$(a,b)$,问你整数$x$和$y$分别取多少时,有$ax+by=gcd(x,y)$,其中$gcd(x,y)$表示$x$和$y$的最大公约数. 数据范围$a,b≤10^ ...

  5. npm私服搭建

    本文是在 centos7 下利用 nexus 搭建 npm 私服的整理 一.安装 JDK 1.下载 JDK 2.安装 tar zxvf jdk-8u191-linux-x64.tar.gz .0_19 ...

  6. POJ 2498

    #include<iostream> using namespace std; #include<string> #include<stdio.h> int mai ...

  7. Dev Label显示不同颜色字体

    labelControl1.Text = "<size=14>Size = 14<br>" + "<b>Bold</b> ...

  8. Spark集群之Spark history server额外配置

     Note: driver在SparkContext使用stop()方法后才将完整的信息提交到指定的目录,如果不使用stop()方法,即使在指定目录中产生该应用程序的目录,history server ...

  9. Linux下dmesg命令处理故障和收集系统信息的7种用法

    目录: <syslog之一:Linux syslog日志系统详解> <syslog之二:syslog协议及rsyslog服务全解析> <syslog之三:建立Window ...

  10. sparkshell运行sql报错: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

    下载msyql的连接driver https://download.csdn.net/download/xz360717118/10662304 把其中一个: mysql-connector-java ...