设计模式:备忘录(Memento)模式
一、前言
备忘录模式用于保存和恢复对象的状态,相信大家看过我前面的拙作就会想到原型模式也能保存一个对象在某一个时刻的状态,那么两者有何不同的呢?原型模式保存的是当前对象的所有状态信息,恢复的时候会生成与保存的对象完全相同的另外一个实例;而备忘录模式保存的是我们关心的在恢复时需要的对象的部分状态信息,相当于快照。备忘录模式大家肯定都见过,比如在玩游戏的时候有一个保存当前闯关的状态的功能,会对当前用户所处的状态进行保存,当用户闯关失败或者需要从快照的地方开始的时候,就能读取当时保存的状态完整地恢复到当时的环境,这一点和VMware上面的快照功能很类似。
二、代码
Memento类:
1 package zyr.dp.memento; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class Memento { 7 8 private int menoy; 9 private ArrayList fruits; 10 11 //窄接口,访问部分信息 12 public int getMenoy(){ 13 return menoy; 14 } 15 16 //宽接口,本包之内皆可访问 17 Memento(int menoy){ 18 this.menoy=menoy; 19 fruits=new ArrayList();//每次调用的时候重新生成,很重要 20 } 21 //宽接口,本包之内皆可访问 22 List getFruits(){ 23 return (List) fruits.clone(); 24 } 25 //宽接口,本包之内皆可访问 26 void addFruits(String fruit){ 27 fruits.add(fruit); 28 } 29 30 }
Gamer 类:
1 package zyr.dp.memento; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.Random; 7 8 public class Gamer { 9 10 private static String[] FruitsSame={"香蕉","苹果","橘子","柚子"}; 11 12 private int menoy; 13 private List fruits=new ArrayList(); 14 private Random random=new Random(); 15 16 public int getMenoy(){ 17 return menoy; 18 } 19 20 public Gamer(int menoy){ 21 this.menoy=menoy; 22 } 23 24 public void bet(){ 25 int next=random.nextInt(6)+1; 26 if(next==1){ 27 menoy+=100; 28 System.out.println("金钱增加了100,当前金钱为:"+menoy); 29 }else if(next==2){ 30 menoy/=2; 31 System.out.println("金钱减少了一半,当前金钱为:"+menoy); 32 }else if(next==6){ 33 String f=getFruit(); 34 fruits.add(f); 35 System.out.println("获得了水果:"+f+",当前金钱为:"+menoy); 36 }else { 37 System.out.println("金钱没有发生改变,当前金钱为:"+menoy); 38 } 39 } 40 41 private String getFruit() { 42 43 String prefix=""; 44 if(random.nextBoolean()){ 45 prefix="好吃的"; 46 } 47 return prefix+FruitsSame[random.nextInt(FruitsSame.length)]; 48 49 } 50 51 public Memento createMemento(){ 52 Memento m=new Memento(menoy); 53 Iterator it=fruits.iterator(); 54 while(it.hasNext()){ 55 String fruit=(String)it.next(); 56 if(fruit.startsWith("好吃的")){ 57 m.addFruits(fruit); 58 } 59 } 60 return m; 61 } 62 63 public void restoreMemento(Memento memento){ 64 this.menoy=memento.getMenoy(); 65 this.fruits=memento.getFruits(); 66 } 67 68 public String toString(){ 69 return "Menoy:"+menoy+" ,Fruits:"+fruits; 70 } 71 72 }
Main类:
1 package zyr.dp.test; 2 3 import zyr.dp.memento.Gamer; 4 import zyr.dp.memento.Memento; 5 6 public class Main { 7 8 public static void main(String[] args) { 9 Gamer gamer=new Gamer(100); 10 Memento memento=gamer.createMemento(); 11 for(int i=0;i<100;i++){ 12 System.out.println("当前状态:"+i); 13 System.out.println("当前金额:"+gamer.getMenoy()); 14 gamer.bet(); 15 if(gamer.getMenoy()<memento.getMenoy()/2){ 16 System.out.println("金钱过少,恢复到以前的状态:"); 17 gamer.restoreMemento(memento); 18 System.out.println("此时状态为:"+gamer); 19 }else if(gamer.getMenoy()>memento.getMenoy()){ 20 System.out.println("金钱增多,保存当前状态:"); 21 memento=gamer.createMemento(); 22 System.out.println("此时状态为:"+gamer); 23 } 24 try { 25 Thread.sleep(500); 26 } catch (InterruptedException e) { 27 e.printStackTrace(); 28 } 29 } 30 31 } 32 33 }
运行结果:
当前状态:0 当前金额:100 金钱没有发生改变,当前金钱为:100 当前状态:1 当前金额:100 金钱增加了100,当前金钱为:200 金钱增多,保存当前状态: 此时状态为:Menoy:200 ,Fruits:[] 当前状态:2 当前金额:200 金钱增加了100,当前金钱为:300 金钱增多,保存当前状态: 此时状态为:Menoy:300 ,Fruits:[] 当前状态:3 当前金额:300 金钱减少了一半,当前金钱为:150 当前状态:4 当前金额:150 金钱减少了一半,当前金钱为:75 金钱过少,恢复到以前的状态: 此时状态为:Menoy:300 ,Fruits:[] 当前状态:5 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:6 当前金额:300 金钱增加了100,当前金钱为:400 金钱增多,保存当前状态: 此时状态为:Menoy:400 ,Fruits:[] 当前状态:7 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:8 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:9 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:10 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:11 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:12 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:13 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:14 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:15 当前金额:300 金钱增加了100,当前金钱为:400 当前状态:16 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:17 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:18 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:19 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:20 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:21 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:22 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:23 当前金额:200 获得了水果:橘子,当前金钱为:200 当前状态:24 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:25 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:26 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:27 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:28 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:29 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:30 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:31 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:32 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:33 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:34 当前金额:300 获得了水果:橘子,当前金钱为:300 当前状态:35 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:36 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:37 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:38 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:39 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:40 当前金额:300 金钱减少了一半,当前金钱为:150 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[] 当前状态:41 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:42 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:43 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:44 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:45 当前金额:200 金钱减少了一半,当前金钱为:100 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[] 当前状态:46 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:47 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:48 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:49 当前金额:400 获得了水果:香蕉,当前金钱为:400 当前状态:50 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:51 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:52 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:53 当前金额:300 金钱减少了一半,当前金钱为:150 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[] 当前状态:54 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:55 当前金额:200 获得了水果:好吃的柚子,当前金钱为:200 当前状态:56 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:57 当前金额:200 获得了水果:好吃的香蕉,当前金钱为:200 当前状态:58 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:59 当前金额:200 获得了水果:香蕉,当前金钱为:200 当前状态:60 当前金额:200 获得了水果:苹果,当前金钱为:200 当前状态:61 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:62 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:63 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:64 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:65 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:66 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:67 当前金额:300 金钱减少了一半,当前金钱为:150 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[] 当前状态:68 当前金额:400 金钱增加了100,当前金钱为:500 金钱增多,保存当前状态: 此时状态为:Menoy:500 ,Fruits:[] 当前状态:69 当前金额:500 金钱增加了100,当前金钱为:600 金钱增多,保存当前状态: 此时状态为:Menoy:600 ,Fruits:[] 当前状态:70 当前金额:600 金钱没有发生改变,当前金钱为:600 当前状态:71 当前金额:600 金钱没有发生改变,当前金钱为:600 当前状态:72 当前金额:600 金钱没有发生改变,当前金钱为:600 当前状态:73 当前金额:600 金钱增加了100,当前金钱为:700 金钱增多,保存当前状态: 此时状态为:Menoy:700 ,Fruits:[] 当前状态:74 当前金额:700 金钱增加了100,当前金钱为:800 金钱增多,保存当前状态: 此时状态为:Menoy:800 ,Fruits:[] 当前状态:75 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:76 当前金额:800 获得了水果:好吃的柚子,当前金钱为:800 当前状态:77 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:78 当前金额:800 金钱减少了一半,当前金钱为:400 当前状态:79 当前金额:400 金钱减少了一半,当前金钱为:200 金钱过少,恢复到以前的状态: 此时状态为:Menoy:800 ,Fruits:[] 当前状态:80 当前金额:800 获得了水果:好吃的苹果,当前金钱为:800 当前状态:81 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:82 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:83 当前金额:800 获得了水果:好吃的柚子,当前金钱为:800 当前状态:84 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:85 当前金额:800 金钱没有发生改变,当前金钱为:800 当前状态:86 当前金额:800 金钱增加了100,当前金钱为:900 金钱增多,保存当前状态: 此时状态为:Menoy:900 ,Fruits:[好吃的苹果, 好吃的柚子] 当前状态:87 当前金额:900 金钱减少了一半,当前金钱为:450 当前状态:88 当前金额:450 金钱增加了100,当前金钱为:550 当前状态:89 当前金额:550 金钱增加了100,当前金钱为:650 当前状态:90 当前金额:650 金钱增加了100,当前金钱为:750 当前状态:91 当前金额:750 获得了水果:柚子,当前金钱为:750 当前状态:92 当前金额:750 金钱没有发生改变,当前金钱为:750 当前状态:93 当前金额:750 金钱增加了100,当前金钱为:850 当前状态:94 当前金额:850 金钱减少了一半,当前金钱为:425 金钱过少,恢复到以前的状态: 此时状态为:Menoy:900 ,Fruits:[好吃的苹果, 好吃的柚子] 当前状态:95 当前金额:900 获得了水果:好吃的橘子,当前金钱为:900 当前状态:96 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:97 当前金额:900 金钱增加了100,当前金钱为:1000 金钱增多,保存当前状态: 此时状态为:Menoy:1000 ,Fruits:[好吃的苹果, 好吃的柚子, 好吃的橘子] 当前状态:98 当前金额:1000 金钱减少了一半,当前金钱为:500 当前状态:99 当前金额:500 金钱减少了一半,当前金钱为:250 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1000 ,Fruits:[好吃的苹果, 好吃的柚子, 好吃的橘子]
本程序的功能是根据循环次数随机的生成1~6这6个数字,如果数字是1,则金钱加一百,如果是二,则金钱减半,如果是6,则随机生成水果,水果分为好吃的和不好吃的,在保存的时候只保存好吃的水果,恢复的时候就只有好吃的水果了。当金钱少于当前备忘录中金钱的一半的时候就要恢复到备忘录的状态;当金钱大于备忘录的状态的时候就要备份当前的状态,备份的时候只备份好的水果以及当前金额,这就是游戏的功能,可以看到运行的结果的正确性。
这里有几点要注意:
2.1、窄接口和宽接口
在代码中我已经标注出了窄接口和宽接口,如何定义这两种接口还要看这两种接口前面的修饰符,如果是默认的(只有本包的类可以使用),并且这些接口结合到一起可以完全的将本类的信息显示出来,那么就是宽接口;只能在本包之中使用,如果修饰符是public的接口,并且只能表示本类一部分信息,因为是public可以在其他包中使用的,就是窄接口,只能查看部分信息,因此是窄的。如下图所示,对于Main类所在的包,只能使用其他两个类中声明为public的字段和方法,因此在Main中只能使用窄接口来完成一定信息的读取getMenoy()。这只是一个概念,强调的是类、字段、方法的可见性。
2.2、可见性
同时我们也知道,public修饰的字段和方法在任何包中都可以使用,private修饰的字段和方法只能在本类之中使用,protected修饰的方法可以在本包之中以及该类的子类(可以在其他包)中使用,默认的没有任何修饰的可以在本包之中使用。这就是四种修饰关键字的可见性。在编程的时候我们一定要考虑这些问题,不然就会导致我们不想看到的字段、方法、类被误用的结果。
2.3、将备份内容存盘并且读取
Memento类:
1 package zyr.dp.serializable; 2 3 import java.io.Serializable; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 public class Memento implements Serializable { 8 9 private static final long serialVersionUID = 8497203738547925495L; 10 11 private int menoy; 12 private ArrayList fruits; 13 14 //窄接口,访问部分信息 15 public int getMenoy(){ 16 return menoy; 17 } 18 19 //宽接口,本包之内皆可访问 20 Memento(int menoy){ 21 this.menoy=menoy; 22 fruits=new ArrayList();//每次调用的时候重新生成,很重要 23 } 24 //宽接口,本包之内皆可访问 25 List getFruits(){ 26 return (List) fruits.clone(); 27 } 28 //宽接口,本包之内皆可访问 29 void addFruits(String fruit){ 30 fruits.add(fruit); 31 } 32 33 }
Gamer类:
1 package zyr.dp.serializable; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.Random; 7 8 public class Gamer { 9 10 private static String[] FruitsSame={"香蕉","苹果","橘子","柚子"}; 11 12 private int menoy; 13 private List fruits=new ArrayList(); 14 private Random random=new Random(); 15 16 public int getMenoy(){ 17 return menoy; 18 } 19 20 public Gamer(int menoy){ 21 this.menoy=menoy; 22 } 23 24 public void bet(){ 25 int next=random.nextInt(6)+1; 26 if(next==1){ 27 menoy+=100; 28 System.out.println("金钱增加了100,当前金钱为:"+menoy); 29 }else if(next==2){ 30 menoy/=2; 31 System.out.println("金钱减少了一半,当前金钱为:"+menoy); 32 }else if(next==6){ 33 String f=getFruit(); 34 fruits.add(f); 35 System.out.println("获得了水果:"+f+",当前金钱为:"+menoy); 36 }else { 37 System.out.println("金钱没有发生改变,当前金钱为:"+menoy); 38 } 39 } 40 41 private String getFruit() { 42 43 String prefix=""; 44 if(random.nextBoolean()){ 45 prefix="好吃的"; 46 } 47 return prefix+FruitsSame[random.nextInt(FruitsSame.length)]; 48 49 } 50 51 public Memento createMemento(){ 52 Memento m=new Memento(menoy); 53 Iterator it=fruits.iterator(); 54 while(it.hasNext()){ 55 String fruit=(String)it.next(); 56 if(fruit.startsWith("好吃的")){ 57 m.addFruits(fruit); 58 } 59 } 60 return m; 61 } 62 63 public void restoreMemento(Memento memento){ 64 this.menoy=memento.getMenoy(); 65 this.fruits=memento.getFruits(); 66 } 67 68 public String toString(){ 69 return "Menoy:"+menoy+" ,Fruits:"+fruits; 70 } 71 72 }
SerializableMain类:
1 package zyr.dp.test; 2 3 import java.io.*; 4 5 import zyr.dp.serializable.Gamer; 6 import zyr.dp.serializable.Memento; 7 8 9 public class SerializableMain { 10 11 private static String filename="game.dat"; 12 public static void main(String[] args) { 13 Gamer gamer=new Gamer(100); 14 Memento memento=loadMemento(); 15 16 if(memento==null){ 17 memento=gamer.createMemento(); 18 }else{ 19 System.out.println("从上次保存处开始..."); 20 gamer.restoreMemento(memento); 21 } 22 23 for(int i=0;i<100;i++){ 24 System.out.println("当前状态:"+i); 25 System.out.println("当前金额:"+gamer.getMenoy()); 26 gamer.bet(); 27 if(gamer.getMenoy()<memento.getMenoy()/2){ 28 System.out.println("金钱过少,恢复到以前的状态:"); 29 gamer.restoreMemento(memento); 30 System.out.println("此时状态为:"+gamer); 31 }else if(gamer.getMenoy()>memento.getMenoy()){ 32 System.out.println("金钱增多,保存当前状态:"); 33 memento=gamer.createMemento(); 34 saveMemento(memento); 35 System.out.println("此时状态为:"+gamer); 36 } 37 try { 38 Thread.sleep(500); 39 } catch (InterruptedException e) { 40 e.printStackTrace(); 41 } 42 } 43 44 } 45 private static void saveMemento(Memento memento) { 46 try { 47 ObjectOutput o=new ObjectOutputStream(new FileOutputStream(filename)); 48 o.writeObject(memento); 49 o.close(); 50 } catch (FileNotFoundException e) { 51 e.printStackTrace(); 52 } catch (IOException e) { 53 e.printStackTrace(); 54 } 55 } 56 private static Memento loadMemento() { 57 Memento memento=null; 58 ObjectInput in; 59 try { 60 in = new ObjectInputStream(new FileInputStream(filename)); 61 memento=(Memento)in.readObject(); 62 in.close(); 63 } catch (FileNotFoundException e) { 64 System.out.println(e.toString()); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } catch (ClassNotFoundException e) { 68 e.printStackTrace(); 69 } 70 return memento; 71 } 72 73 }
运行结果:
初次运行:
java.io.FileNotFoundException: game.dat (系统找不到指定的文件。) 当前状态:0 当前金额:100 获得了水果:好吃的苹果,当前金钱为:100 当前状态:1 当前金额:100 金钱没有发生改变,当前金钱为:100 当前状态:2 当前金额:100 金钱没有发生改变,当前金钱为:100 当前状态:3 当前金额:100 金钱没有发生改变,当前金钱为:100 当前状态:4 当前金额:100 获得了水果:苹果,当前金钱为:100 当前状态:5 当前金额:100 金钱没有发生改变,当前金钱为:100 当前状态:6 当前金额:100 金钱增加了100,当前金钱为:200 金钱增多,保存当前状态: 此时状态为:Menoy:200 ,Fruits:[好吃的苹果, 苹果] 当前状态:7 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:8 当前金额:200 金钱增加了100,当前金钱为:300 金钱增多,保存当前状态: 此时状态为:Menoy:300 ,Fruits:[好吃的苹果, 苹果] 当前状态:9 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:10 当前金额:300 获得了水果:橘子,当前金钱为:300 当前状态:11 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:12 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:13 当前金额:300 金钱增加了100,当前金钱为:400 金钱增多,保存当前状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果, 苹果, 橘子] 当前状态:14 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:15 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:16 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:17 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:18 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:19 当前金额:200 获得了水果:好吃的柚子,当前金钱为:200 当前状态:20 当前金额:200 获得了水果:好吃的柚子,当前金钱为:200 当前状态:21 当前金额:200 金钱减少了一半,当前金钱为:100 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果] 当前状态:22 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:23 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:24 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:25 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:26 当前金额:300 金钱没有发生改变,当前金钱为:300 当前状态:27 当前金额:300 金钱减少了一半,当前金钱为:150 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果] 当前状态:28 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:29 当前金额:400 获得了水果:香蕉,当前金钱为:400 当前状态:30 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:31 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:32 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:33 当前金额:200 获得了水果:柚子,当前金钱为:200 当前状态:34 当前金额:200 金钱减少了一半,当前金钱为:100 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果] 当前状态:35 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:36 当前金额:400 获得了水果:橘子,当前金钱为:400 当前状态:37 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:38 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:39 当前金额:200 获得了水果:好吃的橘子,当前金钱为:200 当前状态:40 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:41 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:42 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:43 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:44 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:45 当前金额:200 金钱增加了100,当前金钱为:300 当前状态:46 当前金额:300 金钱减少了一半,当前金钱为:150 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果] 当前状态:47 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:48 当前金额:400 金钱减少了一半,当前金钱为:200 当前状态:49 当前金额:200 获得了水果:柚子,当前金钱为:200 当前状态:50 当前金额:200 金钱没有发生改变,当前金钱为:200 当前状态:51 当前金额:200 金钱减少了一半,当前金钱为:100 金钱过少,恢复到以前的状态: 此时状态为:Menoy:400 ,Fruits:[好吃的苹果] 当前状态:52 当前金额:400 获得了水果:香蕉,当前金钱为:400 当前状态:53 当前金额:400 金钱没有发生改变,当前金钱为:400 当前状态:54 当前金额:400 金钱增加了100,当前金钱为:500 金钱增多,保存当前状态: 此时状态为:Menoy:500 ,Fruits:[好吃的苹果, 香蕉] 当前状态:55 当前金额:500 金钱减少了一半,当前金钱为:250 当前状态:56 当前金额:250 获得了水果:好吃的苹果,当前金钱为:250 当前状态:57 当前金额:250 金钱减少了一半,当前金钱为:125 金钱过少,恢复到以前的状态: 此时状态为:Menoy:500 ,Fruits:[好吃的苹果] 当前状态:58 当前金额:500 金钱没有发生改变,当前金钱为:500 当前状态:59 当前金额:500 获得了水果:柚子,当前金钱为:500 当前状态:60 当前金额:500 金钱减少了一半,当前金钱为:250 当前状态:61 当前金额:250 金钱没有发生改变,当前金钱为:250 当前状态:62 当前金额:250 金钱增加了100,当前金钱为:350 当前状态:63 当前金额:350 金钱没有发生改变,当前金钱为:350 当前状态:64 当前金额:350 金钱减少了一半,当前金钱为:175 金钱过少,恢复到以前的状态: 此时状态为:Menoy:500 ,Fruits:[好吃的苹果] 当前状态:65 当前金额:500 获得了水果:柚子,当前金钱为:500 当前状态:66 当前金额:500 金钱增加了100,当前金钱为:600 金钱增多,保存当前状态: 此时状态为:Menoy:600 ,Fruits:[好吃的苹果, 柚子] 当前状态:67 当前金额:600 金钱没有发生改变,当前金钱为:600 当前状态:68 当前金额:600 金钱增加了100,当前金钱为:700 金钱增多,保存当前状态: 此时状态为:Menoy:700 ,Fruits:[好吃的苹果, 柚子] 当前状态:69 当前金额:700 获得了水果:好吃的橘子,当前金钱为:700 当前状态:70 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:71 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:72 当前金额:700 获得了水果:香蕉,当前金钱为:700 当前状态:73 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:74 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:75 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:76 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:77 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:78 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:79 当前金额:700 金钱没有发生改变,当前金钱为:700 当前状态:80 当前金额:700 金钱增加了100,当前金钱为:800 金钱增多,保存当前状态: 此时状态为:Menoy:800 ,Fruits:[好吃的苹果, 柚子, 好吃的橘子, 香蕉] 当前状态:81 当前金额:800 金钱增加了100,当前金钱为:900 金钱增多,保存当前状态: 此时状态为:Menoy:900 ,Fruits:[好吃的苹果, 柚子, 好吃的橘子, 香蕉] 当前状态:82 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:83 当前金额:900 获得了水果:柚子,当前金钱为:900 当前状态:84 当前金额:900 金钱减少了一半,当前金钱为:450 当前状态:85 当前金额:450 金钱没有发生改变,当前金钱为:450 当前状态:86 当前金额:450 金钱增加了100,当前金钱为:550 当前状态:87 当前金额:550 获得了水果:好吃的柚子,当前金钱为:550 当前状态:88 当前金额:550 金钱没有发生改变,当前金钱为:550 当前状态:89 当前金额:550 金钱没有发生改变,当前金钱为:550 当前状态:90 当前金额:550 金钱没有发生改变,当前金钱为:550 当前状态:91 当前金额:550 获得了水果:好吃的香蕉,当前金钱为:550 当前状态:92 当前金额:550 金钱减少了一半,当前金钱为:275 金钱过少,恢复到以前的状态: 此时状态为:Menoy:900 ,Fruits:[好吃的苹果, 好吃的橘子] 当前状态:93 当前金额:900 金钱增加了100,当前金钱为:1000 金钱增多,保存当前状态: 此时状态为:Menoy:1000 ,Fruits:[好吃的苹果, 好吃的橘子] 当前状态:94 当前金额:1000 获得了水果:橘子,当前金钱为:1000 当前状态:95 当前金额:1000 金钱减少了一半,当前金钱为:500 当前状态:96 当前金额:500 金钱没有发生改变,当前金钱为:500 当前状态:97 当前金额:500 金钱没有发生改变,当前金钱为:500 当前状态:98 当前金额:500 获得了水果:柚子,当前金钱为:500 当前状态:99 当前金额:500 获得了水果:柚子,当前金钱为:500
第二次运行:
从上次保存处开始... 当前状态:0 当前金额:1000 金钱没有发生改变,当前金钱为:1000 当前状态:1 当前金额:1000 金钱增加了100,当前金钱为:1100 金钱增多,保存当前状态: 此时状态为:Menoy:1100 ,Fruits:[好吃的苹果, 好吃的橘子] 当前状态:2 当前金额:1100 金钱增加了100,当前金钱为:1200 金钱增多,保存当前状态: 此时状态为:Menoy:1200 ,Fruits:[好吃的苹果, 好吃的橘子] 当前状态:3 当前金额:1200 获得了水果:香蕉,当前金钱为:1200 当前状态:4 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:5 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:6 当前金额:1200 获得了水果:好吃的橘子,当前金钱为:1200 当前状态:7 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:8 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:9 当前金额:1200 获得了水果:好吃的苹果,当前金钱为:1200 当前状态:10 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:11 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:12 当前金额:1200 获得了水果:好吃的橘子,当前金钱为:1200 当前状态:13 当前金额:1200 获得了水果:好吃的柚子,当前金钱为:1200 当前状态:14 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:15 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:16 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:17 当前金额:1200 获得了水果:苹果,当前金钱为:1200 当前状态:18 当前金额:1200 金钱没有发生改变,当前金钱为:1200 当前状态:19 当前金额:1200 金钱增加了100,当前金钱为:1300 金钱增多,保存当前状态: 此时状态为:Menoy:1300 ,Fruits:[好吃的苹果, 好吃的橘子, 香蕉, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子, 苹果] 当前状态:20 当前金额:1300 金钱没有发生改变,当前金钱为:1300 当前状态:21 当前金额:1300 金钱减少了一半,当前金钱为:650 当前状态:22 当前金额:650 获得了水果:好吃的苹果,当前金钱为:650 当前状态:23 当前金额:650 金钱增加了100,当前金钱为:750 当前状态:24 当前金额:750 金钱减少了一半,当前金钱为:375 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1300 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:25 当前金额:1300 金钱没有发生改变,当前金钱为:1300 当前状态:26 当前金额:1300 金钱增加了100,当前金钱为:1400 金钱增多,保存当前状态: 此时状态为:Menoy:1400 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:27 当前金额:1400 金钱没有发生改变,当前金钱为:1400 当前状态:28 当前金额:1400 金钱没有发生改变,当前金钱为:1400 当前状态:29 当前金额:1400 金钱增加了100,当前金钱为:1500 金钱增多,保存当前状态: 此时状态为:Menoy:1500 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:30 当前金额:1500 金钱增加了100,当前金钱为:1600 金钱增多,保存当前状态: 此时状态为:Menoy:1600 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:31 当前金额:1600 金钱没有发生改变,当前金钱为:1600 当前状态:32 当前金额:1600 金钱没有发生改变,当前金钱为:1600 当前状态:33 当前金额:1600 金钱没有发生改变,当前金钱为:1600 当前状态:34 当前金额:1600 金钱增加了100,当前金钱为:1700 金钱增多,保存当前状态: 此时状态为:Menoy:1700 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:35 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:36 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:37 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:38 当前金额:1700 金钱减少了一半,当前金钱为:850 当前状态:39 当前金额:850 金钱没有发生改变,当前金钱为:850 当前状态:40 当前金额:850 金钱没有发生改变,当前金钱为:850 当前状态:41 当前金额:850 金钱没有发生改变,当前金钱为:850 当前状态:42 当前金额:850 金钱没有发生改变,当前金钱为:850 当前状态:43 当前金额:850 金钱增加了100,当前金钱为:950 当前状态:44 当前金额:950 金钱减少了一半,当前金钱为:475 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1700 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:45 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:46 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:47 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:48 当前金额:1700 金钱没有发生改变,当前金钱为:1700 当前状态:49 当前金额:1700 金钱增加了100,当前金钱为:1800 金钱增多,保存当前状态: 此时状态为:Menoy:1800 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:50 当前金额:1800 金钱减少了一半,当前金钱为:900 当前状态:51 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:52 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:53 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:54 当前金额:900 获得了水果:好吃的柚子,当前金钱为:900 当前状态:55 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:56 当前金额:900 金钱没有发生改变,当前金钱为:900 当前状态:57 当前金额:900 获得了水果:好吃的柚子,当前金钱为:900 当前状态:58 当前金额:900 金钱减少了一半,当前金钱为:450 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1800 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:59 当前金额:1800 金钱增加了100,当前金钱为:1900 金钱增多,保存当前状态: 此时状态为:Menoy:1900 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:60 当前金额:1900 金钱没有发生改变,当前金钱为:1900 当前状态:61 当前金额:1900 金钱没有发生改变,当前金钱为:1900 当前状态:62 当前金额:1900 金钱没有发生改变,当前金钱为:1900 当前状态:63 当前金额:1900 获得了水果:好吃的柚子,当前金钱为:1900 当前状态:64 当前金额:1900 金钱没有发生改变,当前金钱为:1900 当前状态:65 当前金额:1900 金钱减少了一半,当前金钱为:950 当前状态:66 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:67 当前金额:950 获得了水果:柚子,当前金钱为:950 当前状态:68 当前金额:950 金钱减少了一半,当前金钱为:475 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1900 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:69 当前金额:1900 金钱减少了一半,当前金钱为:950 当前状态:70 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:71 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:72 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:73 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:74 当前金额:950 金钱增加了100,当前金钱为:1050 当前状态:75 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:76 当前金额:1050 获得了水果:好吃的香蕉,当前金钱为:1050 当前状态:77 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:78 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:79 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:80 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:81 当前金额:1050 获得了水果:柚子,当前金钱为:1050 当前状态:82 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:83 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:84 当前金额:1050 金钱增加了100,当前金钱为:1150 当前状态:85 当前金额:1150 金钱没有发生改变,当前金钱为:1150 当前状态:86 当前金额:1150 金钱增加了100,当前金钱为:1250 当前状态:87 当前金额:1250 金钱减少了一半,当前金钱为:625 金钱过少,恢复到以前的状态: 此时状态为:Menoy:1900 ,Fruits:[好吃的苹果, 好吃的橘子, 好吃的橘子, 好吃的苹果, 好吃的橘子, 好吃的柚子] 当前状态:88 当前金额:1900 获得了水果:苹果,当前金钱为:1900 当前状态:89 当前金额:1900 金钱减少了一半,当前金钱为:950 当前状态:90 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:91 当前金额:950 获得了水果:好吃的橘子,当前金钱为:950 当前状态:92 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:93 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:94 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:95 当前金额:950 金钱没有发生改变,当前金钱为:950 当前状态:96 当前金额:950 获得了水果:好吃的橘子,当前金钱为:950 当前状态:97 当前金额:950 金钱增加了100,当前金钱为:1050 当前状态:98 当前金额:1050 金钱没有发生改变,当前金钱为:1050 当前状态:99 当前金额:1050 金钱没有发生改变,当前金钱为:1050
可以看到保存和读取成功。
三、总结
备忘录模式也是一种比较常用的模式用来保存对象的部分用于恢复的信息,和原型模式有着本质的区别,广泛运用在快照功能之中,另外我们知道了宽接口和窄接口,这里的接口就是指的方法,没有其他意思,以及类的可见性。同样的使用备忘录模式可以使得程序可以组件化,比如打算多次撤销当前的状态,以及不仅可以撤销而且可以将当前的状态保存到文件之中的时候,我们不需要修改Gamer的代码就能做到,职责明确是一种非常重要的是软件工程思想。