设计模式:备忘录(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:[好吃的苹果, 好吃的柚子, 好吃的橘子]