004-行为型-07-备忘录模式(Memento)
一、概述
又叫做快照模式(Snapshot Pattern)或Token模式
保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。
意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
备忘录模式和状态模式:备忘录模式是对象表示状态,状态模式是用类来表示状态。
1.1、适用场景
1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。
(1)一个类需要保存它的对象的状态(相当于Originator角色)
(2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色)
(3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存
(4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态
1.2、优缺点
优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
1.3、类图角色及其职责
1、Originator(原生者):需要被保存状态以便恢复的那个对象,负责创建一个备忘录Memento,用以记录当前时刻自身的内部状态,并可使用备忘录恢复内部状态。Originator可以根据需要决定Memento存储自己的哪些内部状态。
2、Memento(备忘录):该对象由Originator创建,主要负责存储Originator对象的内部状态,并可以防止Originator以外的其他对象访问备忘录。备忘录有两个接口:Caretaker只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator却可看到备忘录的宽接口,允许它访问返回到先前状
态所需要的所有数据。
3、Caretaker(管理者):负责在适当的时间保存/恢复Originator对象的状态,负责备忘录Memento,不能对Memento的内容进行访问或者操作。
1.4、演进过程
首先,新建一个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; } }
创建管理者Caretaker(管理者)角色
/* * Caretaker(管理者) */ public class Caretaker { //持有一个对Memento的引用 private Memento memento; public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } }
测试
@Test public void test() { 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(); }
输出
name:小明,sex:男,age:18 name:小红,sex:女,age:17 name:小明,sex:男,age:18
二、扩展
2.1、spring
org.springframework.binding.message.StateManageableMessageContext
数据库的事务管理。