设计模式之备忘录模式

来源:互联网 发布:现代进化论 知乎 编辑:程序博客网 时间:2024/05/19 08:26

一、定义

   这个模式就是保存某个对象某个时刻的状态,并且通过某种方式能够使对象恢复到这个时刻的状态。

二、实例

假如你要到某个小镇,在路上你遇到个三叉路口,你不知道应该选择哪一个,因此你必须一个一个去尝试直到到达小镇。每一次尝试一条路之后,如果行不通你都要返回到三岔路口,尝试下一条路。这时候你就需要备忘录模式,记下这个三叉路口的位置。首先定义一个walker,其中的state代表他此时的状态是回到了岔口还是尝试一条路。
public class Walker { private String state = null ; public String getState() {  return state; } public void setState(String state) {  this.state = state; } public MemoRandum restoreMemo() {  return new MemoRandum(this.state); } public void backupMemo(MemoRandum memoRandum) {  this.state = memoRandum.getState(); }}
    然后有一个备忘录类:
public class MemoRandum { private String state = null ; public MemoRandum(String state) {  this.state = state; } public String getState() {  return state; } public void setState(String state) {  this.state = state; }}
    一个备忘录的管理类,负责备忘录的创建和记录    
public class MemoManager { private MemoRandum memoRandum = null ; public MemoManager(MemoRandum memoRandum) {  this.memoRandum = memoRandum; } public MemoRandum getMemoRandum() {  return memoRandum; } public void setMemoRandum(MemoRandum memoRandum) {  this.memoRandum = memoRandum; }}
 测试代码
Walker xiaoming = new Walker();  xiaoming.setState("停在岔路口");  System.out.println("========xiaoming的此时的状态=======");  System.out.println(xiaoming.getState());  System.out.println("========xiaoming保存状态之后=======");  MemoManager memoManager = new MemoManager(xiaoming.restoreMemo());  xiaoming.setState("尝试一个路口");  System.out.println(xiaoming.getState());  System.out.println("========xiaoming回复之前的状态======");  xiaoming.backupMemo(memoManager.getMemoRandum());  System.out.println(xiaoming.getState());
结果:
========xiaoming的此时的状态=======停在岔路口========xiaoming保存状态之后=======尝试一个路口========xiaoming回复之前的状态======停在岔路口
   在这个例子中,就是很简单的将walker类的一个变量在改变之前先存放到另外一个类里面,而这个存放的过程是用一个专门的类完成的。实际上,管理类的存在对于上层模块来说并不重要,我想要给walker备份的时候,不一定要通过一个专门的类,通过walker自身也是可以的。    上面的walker改成如下。其实只是把对备忘录的定义和记录放在了walker类里面而已。
public class Walker2 { private MemoRandum memoRandum = null ; private String state = null ; public MemoRandum getMemoRandum() {  return memoRandum; } public void setMemoRandum(MemoRandum memoRandum) {  this.memoRandum = memoRandum; } public String getState() {  return state; } public void setState(String state) {  this.state = state; } public void createMemo() {  this.setMemoRandum(new MemoRandum(this.state)); } public void backupMemo() {  this.setState(this.getMemoRandum().getState()); }}
测试代码:
Walker2 xiaoming2 = new Walker2();  xiaoming2.setState("停在岔路口");  System.out.println("========xiaoming2的此时的状态=======");  System.out.println(xiaoming2.getState());  System.out.println("========xiaoming2保存状态之后=======");  xiaoming2.createMemo();  xiaoming2.setState("尝试一个路口");  System.out.println(xiaoming2.getState());  System.out.println("========xiaoming2回复之前的状态======");  xiaoming2.backupMemo();  System.out.println(xiaoming2.getState());
结果:
========xiaoming2的此时的状态=======停在岔路口========xiaoming2保存状态之后=======尝试一个路口========xiaoming2回复之前的状态======停在岔路口

三、扩展

    看完上面的例子,你肯定会说上面的walker只有一个属性,那如果属性很多怎么办呢,一个一个去set吗?不,当然有好的方法!我们玩闯关类游戏的时候都用过存档功能,在过一个很难的关之前先备份一下可以为自己以后省去很多麻烦。那我们就用备忘录模式来实现一下。    首先先定义一个游戏的角色类。其中createMemo和backupMemo函数负责保存和恢复,BeanUtil类是我们自己写的,接下来会说到。
public class GameRole { private String name = null ; private int enegy = 0; private int blood = 0; private MemoRandum2 memoRandum2 = new MemoRandum2() ; public GameRole(String name,int enegy,int blood) {  this.name = name ;  this.enegy = enegy;  this.blood = blood; } public void createMemo() {  this.memoRandum2.setPros(BeanUtil.getHashMap(this)); } public void backupMemo() {  BeanUtil.setHashMap(this.memoRandum2.getPros(), this); } public String getName() {  return name; } public void setName(String name) {  this.name = name; } public int getEnegy() {  return enegy; } public void setEnegy(int enegy) {  this.enegy = enegy; } public int getBlood() {  return blood; } public void setBlood(int blood) {  this.blood = blood; } public void print() {  System.out.println("name:"+this.name+" blood:"+this.blood+" enegy:"+this.enegy); }}
由于备份的数据多起来了,备忘录的类也要改变一下,我们用一个HashMap类型来存变量。
public class MemoRandum2 { private HashMap<String, Object> pros = new HashMap<String, Object>(); public HashMap<String, Object> getPros() {  return pros; } public void setPros(HashMap<String, Object> pros) {  this.pros = pros; }}
接下来说一下BeanUtil类(很重要),这个类负责将一个类里面的属性放到HashMap里面或者将HashMap里面的属性放到一个类里面。(注意看代码中的注解)
public class BeanUtil { /*  * 功能:将一个类里面的参数放到HashMap里面并返回这个HashMap  * 参数object:属性值得来源类,这个函数就是从object中去取属性  */ public static HashMap<String, Object> getHashMap(Object object) {  HashMap<String, Object> result = new HashMap<String, Object>();//先定义一个HashMap  try {   BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());//取对object类的描述   //取object类里面所有属性的描述, beanInfo.getPropertyDescriptors()返回的是一个数组,这个数组里面的每一个元素都是一个对object中属性的描述类。   PropertyDescriptor[] pros = beanInfo.getPropertyDescriptors();   //遍历每一个属性   for (PropertyDescriptor des : pros) {    //取属性名    String name = des.getName();    //如果某个属性的类别不是普通变量而是一个对象的话,它的名称就是class    if(name.equals("class")){     continue;    }    //取属性的读取方法并执行    Method method = des.getReadMethod();    //invoke就是执行这个方法,执行object中的method对应的方法并将返回值赋值给value    //这个里面的new Object[]{}这个似乎没什么用啊    Object value = method.invoke(object, new Object[]{});    result.put(name, value);   }  } catch (Exception e) {   // TODO Auto-generated catch block   e.printStackTrace();  }  return result; } public static void setHashMap(HashMap<String, Object> map,Object object) {  try {   BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());   PropertyDescriptor[] pros = beanInfo.getPropertyDescriptors();   for (PropertyDescriptor des : pros) {    String name = des.getName();    if(name.equals("class")){     continue;    }    Method write = des.getWriteMethod();    Object value = map.get(name);    //执行object中write对应的方法,传入的参数为  new Object[]{map.get(name)}    write.invoke(object, new Object[]{map.get(name)});   }  } catch (Exception e) {   // TODO Auto-generated catch block   e.printStackTrace();  } }}
测试代码:
GameRole crazy = new GameRole("crazy", 10, 10);  System.out.println("=====crazy初始状态=======");  crazy.print();  System.out.println("=====crazy打怪过后=======");  crazy.createMemo();  crazy.setEnegy(8);  crazy.setBlood(5);  crazy.print();  System.out.println("=====crazy恢复到先前状态======");  crazy.backupMemo();  crazy.print();

结果:

=====crazy初始状态=======name:crazy blood:10 enegy:10=====crazy打怪过后=======pros4name:crazy blood:5 enegy:8=====crazy恢复到先前状态======name:crazy blood:10 enegy:10
这样,一个能够保存多个属性的备忘录模式就做好了。这是你可能又会问,玩游戏的时候可以存很多个档啊,想恢复到那个就恢复到哪个。OK,我们就来实现一下。这个时候只要修改GameRole角色就好了。我们用HashMap类型来等级备忘录,并给每个备忘录写上名字。这样只要修改一下createMemo和backupMemo函数就行了。
public class GameRole2 { private HashMap<String, MemoRandum2> memos = new HashMap<String, MemoRandum2>(); private String name = null ; private int enegy = 0; private int blood = 0; public GameRole2(String name,int enegy,int blood) {  this.name = name ;  this.enegy = enegy;  this.blood = blood; } public void createMemo(String ids) {  MemoRandum2 memoRandum2 = new MemoRandum2();  memoRandum2.setPros(BeanUtil.getHashMap(this));  this.memos.put(ids, memoRandum2); } public boolean backupMemo(String ids) {  MemoRandum2 memoRandum2 = this.memos.get(ids);  if(memoRandum2 != null){   BeanUtil.setHashMap(memoRandum2.getPros(), this);   return true;  }else {   return false;  } } public String getName() {  return name; } public void setName(String name) {  this.name = name; } public int getEnegy() {  return enegy; } public void setEnegy(int enegy) {  this.enegy = enegy; } public int getBlood() {  return blood; } public void setBlood(int blood) {  this.blood = blood; } public void print() {  System.out.println("name:"+this.name+" blood:"+this.blood+" enegy:"+this.enegy); }}
测试一下:
GameRole2 crazy2 = new GameRole2("crazy2", 10, 10);  System.out.println("=====crazy2初始状态=======");  crazy2.print();  crazy2.createMemo("初始");  System.out.println("=====crazy2打怪过后状态1=======");  crazy2.setBlood(8);  crazy2.setEnegy(4);  crazy2.print();  crazy2.createMemo("状态1");  System.out.println("=====crazy2打怪过后状态2=======");  crazy2.setBlood(7);  crazy2.setEnegy(2);  crazy2.print();  crazy2.createMemo("状态2");  System.out.println("=====crazy2恢复到初始状态======");  crazy2.backupMemo("初始");  crazy2.print();  System.out.println("=====crazy2恢复到状态1======");  crazy2.backupMemo("状态1");  crazy2.print();
结果:
=====crazy2初始状态=======name:crazy2 blood:10 enegy:10pros4=====crazy2打怪过后状态1=======name:crazy2 blood:8 enegy:4pros4=====crazy2打怪过后状态2=======name:crazy2 blood:7 enegy:2pros4=====crazy2恢复到初始状态======name:crazy2 blood:10 enegy:10=====crazy2恢复到状态1======name:crazy2 blood:8 enegy:4
0 0
原创粉丝点击