java设计模式:备忘录模式
前言
备忘录模式能记录一个对象的内部状态,当用户后悔时能撤销当前操作,使数据恢复到它原先的状态。
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
优点
提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。
实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息。
简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则。
缺点
资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源。
结构
- 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
实现
生活中最常用的计算器自己拥有备忘录的功能,用户计算完后软件会自动为用户记录最后几次的计算结果,我们可以模拟用户使用计算器的过程,以及打开备忘录查看记录。
package com.rabbit;
/**
* 备忘录发起人,模拟计算器加法运算
* Created by HASEE on 2018/4/29.
*/
public class Originator {
private double num1;
private double num2;
//创建备忘录对象
public Memento createMemento() {
return new Memento(num1, num2);
}
public Originator(double num1, double num2) {
this.num1 = num1;
this.num2 = num2;
System.out.println(num1 + " + " + num2 + " = " + (num1 + num2));
}
}
package com.rabbit;
/**
* 备忘录,要保存的属性
* Created by HASEE on 2018/4/29.
*/
public class Memento {
private double num1;//计算器第一个数字
private double num2;//计算器第二个数字
private double result;//计算结果
public Memento(double num1, double num2) {
this.num1 = num1;
this.num2 = num2;
this.result = num1 + num2;
}
public void show() {
System.out.println(num1 + " + " + num2 + " = " + result);
}
}
package com.rabbit;
import java.util.ArrayList;
import java.util.List;
/**
* 备忘录管理者
* Created by HASEE on 2018/4/29.
*/
public class Caretaker {
private List<Memento> mementos;
public boolean addMenento(Memento memento) {
if (mementos == null) {
mementos = new ArrayList<>();
}
return mementos.add(memento);
}
public List<Memento> getMementos() {
return mementos;
}
public static Caretaker newInstance() {
return new Caretaker();
}
}
package com.rabbit;
import org.junit.Test;
import java.util.Random;
/**
* Created by HASEE on 2018/4/29.
*/
public class Demo {
@Test
public void test() {
Caretaker c = Caretaker.newInstance();
//使用循环模拟用户使用计算器做加法运算
Random ran = new Random(1000);
for (int i = 0; i < 5; i++) {
//用户计算
Originator o = new Originator(ran.nextDouble(), ran.nextDouble());
//计算器软件将用户的计算做备份,以便可以查看历史
c.addMenento(o.createMemento());
}
System.out.println("---------------------用户浏览历史记录---------------------");
for (Memento m : c.getMementos()) {
m.show();
}
System.out.println("---------------------用户选择一条记录查看----------------------");
c.getMementos().get(2).show();
}
}