概念:
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(原生者)
1 /* 2 * Originator(原生者) 3 */ 4 public class Person { 5 /* 6 * 姓名,年龄,性别就是结构图中的state,状态属性 7 */ 8 //姓名 9 private String name; 10 //年龄 11 private int age; 12 //性别 13 private String sex; 14 15 public Person() { 16 super(); 17 } 18 19 public Person(String name, int age, String sex) { 20 super(); 21 this.name = name; 22 this.age = age; 23 this.sex = sex; 24 } 25 26 public String getName() { 27 return name; 28 } 29 30 public void setName(String name) { 31 this.name = name; 32 } 33 34 public int getAge() { 35 return age; 36 } 37 38 public void setAge(int age) { 39 this.age = age; 40 } 41 42 public String getSex() { 43 return sex; 44 } 45 46 public void setSex(String sex) { 47 this.sex = sex; 48 } 49 50 public void display() { 51 System.out.println("name:" + name + ",sex:" + sex + ",age:" + age); 52 } 53 54 //创建一个备份 55 public Memento createMemento(){ 56 return new Memento(name,age,sex); 57 } 58 59 //恢复一个备份 60 public void setMemento(Memento memento){ 61 this.name = memento.getName(); 62 this.age = memento.getAge(); 63 this.sex = memento.getSex(); 64 } 65 }
接着,创建一个Memento(备忘录),他和Originator的基本结构是一样的
1 /* 2 * Memento(备忘录) 3 */ 4 public class Memento { 5 //姓名 6 private String name; 7 //年龄 8 private int age; 9 //性别 10 private String sex; 11 12 public Memento() { 13 super(); 14 } 15 16 public Memento(String name, int age, String sex) { 17 super(); 18 this.name = name; 19 this.age = age; 20 this.sex = sex; 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public void setName(String name) { 28 this.name = name; 29 } 30 31 public int getAge() { 32 return age; 33 } 34 35 public void setAge(int age) { 36 this.age = age; 37 } 38 39 public String getSex() { 40 return sex; 41 } 42 43 public void setSex(String sex) { 44 this.sex = sex; 45 } 46 }
接下来,创建客户端运行一下
1 public class MainClass { 2 public static void main(String[] args) { 3 Person person = new Person("小明",18,"男"); 4 //打印 5 person.display(); 6 7 //创建一个备份 8 Memento memento = person.createMemento(); 9 10 person.setName("小红"); 11 person.setAge(17); 12 person.setSex("女"); 13 //打印 14 person.display(); 15 16 //备份还原 17 person.setMemento(memento); 18 //打印 19 person.display(); 20 } 21 }
结果:
这样,就做到了一个备份还原的过程,但是可以看到,根据结构图看,我们还缺少了一个Caretaker(管理者)角色
这个角色的作用其实就是把备份还原的过程交到管理者手中,通过管理者来备份还原
1 /* 2 * Caretaker(管理者) 3 */ 4 public class Caretaker { 5 //持有一个对Memento的引用 6 private Memento memento; 7 8 public Memento getMemento() { 9 return memento; 10 } 11 12 public void setMemento(Memento memento) { 13 this.memento = memento; 14 } 15 }
客户端
1 public class MainClass { 2 public static void main(String[] args) { 3 Person person = new Person("小明",18,"男"); 4 //打印 5 person.display(); 6 7 //创建一个管理者 8 Caretaker caretaker = new Caretaker(); 9 10 //创建一个备份 11 // Memento memento = person.createMemento(); 12 caretaker.setMemento(person.createMemento()); 13 14 person.setName("小红"); 15 person.setAge(17); 16 person.setSex("女"); 17 //打印 18 person.display(); 19 20 //备份还原 21 person.setMemento(caretaker.getMemento()); 22 //打印 23 person.display(); 24 } 25 }
运行结果是一样的