您现在的位置是:网站首页> 内容页

设计模式-备忘录模式

  • 10bet官网app
  • 2019-04-09
  • 60人已阅读
简介备忘录模式:Memento声明/作用:保存对象的内部状态,并在需要的时候(undo/rollback)恢复到对象以前的状态适用场景:一个对象需要保存状态,并且可通过und

备忘录模式 : Memento

声明/作用 : 保存对象的内部状态,并在需要的时候(undo/rollback) 恢复到对象以前的状态

适用场景 : 一个对象需要保存状态,并且可通过undo或者rollback恢复到以前的状态时,可以使用备忘录模式

经典场景 : 某时刻游戏存档恢复记录

需要被保存内部状态以便恢复的这个类 叫做 : Originator 发起人(原生者)

用来保存Originator内部状态的类 叫做 : Memento 备忘录(回忆者) 它由Originator创建

负责管理备忘录Memento的类叫做 : Caretaker 看管者(管理者),它不能对Memento的内容进行访问或者操作。

以Person对象(拥有name,sex,age三个基本属性)为例 : 

package name.ealen.memento.noDesignPattern;/** * Created by EalenXie on 2018/9/27 15:18. */public class Person { private String name; private String sex; private Integer age; public Person(String name, String sex, Integer age) { this.name = name; this.sex = sex; this.age = age; } //省略getter,setter}

 

如果不使用设计模式,我们要对其进行备份,undo操作 ,常规情况下,我们可能会写出如下的代码 : 

 

/** * 不使用设计模式 实现备忘录模式,普通保存实例的内部状态 */ @Test public void noDesignPattern() { Person person = new Person("ealenxie", "男", 23); //1 . 首先新建一个Person的Backup备份,将对象的初始属性赋值进去 Person backup = new Person(); backup.setName(person.getName()); backup.setSex(person.getSex()); backup.setAge(person.getAge()); //打印初始的person System.out.println("初始化的对象 : " + person); //2 . 修改person person.setAge(22); person.setName("ZHANG SAN"); person.setSex("女"); System.out.println("修改后的对象 : " + person); //3 . 回滚(回复以前状态) 从backup中获取之前的状态,重新赋值 person.setAge(backup.getAge()); person.setName(backup.getName()); person.setSex(backup.getSex()); System.out.println("还原后的对象 : " + person); }

运行可以看到基本效果 :  

    

以上代码中,我们首先进行了创建了一个初始对象person,然后new出一个新的backup,将初始对象的属性赋给backup,person修改之后,如果进行undo/rollback,就将backup的属性重新赋值给对象person。这样做我们必须要关注person和backup之间的赋值关系必须一致且值正确,这样才能完成rollback动作;如果person对象拥有诸多属性及行为的话,很显示不是特别的合理。

 

如下,我们使用备忘录模式来完成对象的备份和rollback

  1 . 首先,我们定义Memento对象,它的作用就是用来保存 初始对象(原生者,此例比如person)的内部状态,因此它的属性和原生者应该一致。

package name.ealen.memento.designPattern;/** * Created by EalenXie on 2018/9/27 18:03. */public class Memento { private String name; private String sex; private Integer age; public Memento(String name, String sex, Integer age) { this.name = name; this.sex = sex; this.age = age; } //省略getter/setter}

 

  2 . 然后,定义我们的发起人(原生者) Originator,它拥有两个基本的行为 : 

    1). 创建备份

    2). 根据备份进行rollback

package name.ealen.memento.designPattern;/** * Created by EalenXie on 2018/9/27 18:02. */public class Originator { private String name; private String sex; private Integer age; //创建一个备份 public Memento createMemento() { return new Memento(name, sex, age); } //根据备份进行rollback public void rollbackByMemento(Memento memento) { this.name = memento.getName(); this.sex = memento.getSex(); this.age = memento.getAge(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Originator(String name, String sex, Integer age) { this.name = name; this.sex = sex; this.age = age; } @Override public String toString() { return "Originator{" + "name="" + name + """ + ", sex="" + sex + """ + ", age=" + age + "}"; }}

 

  3 . 为了防止发起者与备份对象的过度耦合,以及防止对发起者行和属性进行过多的代码侵入,我们通常将Memento对象交由CareTaker来进行管理 : 

 

package name.ealen.memento.designPattern;import java.util.HashMap;import java.util.Map;/** * Created by EalenXie on 2018/9/27 17:39. */public class CareTaker { private Map<String, Memento> mementos = new HashMap<>(); //一个或者多个备份录 //保存默认备份 public void saveDefaultMemento(Memento memento) { mementos.put("default", memento); } //获取默认备份 public Memento getMementoByDefault() { return mementos.get("default"); } //根据备份名 保存备份 public void saveMementoByName(String mementoName, Memento memento) { mementos.put(mementoName, memento); } //根据备份名 获取备份 public Memento getMementoByName(String mementoName) { return mementos.get(mementoName); } //删除默认备份 public void deleteDefaultMemento() { mementos.remove("default"); } //根据备份名 删除备份 public void deleteMementoByName(String mementoName) { mementos.remove(mementoName); }}

 

  4 . 此时,我们要进行备份以及rollback,做法如下 : 

 

/** * 备忘录模式,标准实现 */ @Test public void designPattern() { Originator originator = new Originator("ealenxie", "男", 22); CareTaker careTaker = new CareTaker(); //新建一个默认备份,将Originator的初始属性赋值进去 careTaker.saveDefaultMemento(originator.createMemento()); //初始化的Originator System.out.println("初始化的对象 : " + originator); //修改后的Originator originator.setName("ZHANG SAN"); originator.setSex("女"); originator.setAge(23); System.out.println("第一次修改后的对象 : " + originator); //新建一个修改后的备份 careTaker.saveMementoByName("第一次修改备份", originator.createMemento()); //根据默认备份还原rollback后的Originator originator.rollbackByMemento(careTaker.getMementoByDefault()); System.out.println("还原后的对象 : " + originator); //根据备份名还原rollback后的Originator originator.rollbackByMemento(careTaker.getMementoByName("第一次修改备份")); System.out.println("第一次修改备份 : " + originator); //再创建一个默认备份 careTaker.saveDefaultMemento(originator.createMemento()); originator.rollbackByMemento(careTaker.getMementoByDefault()); System.out.println("最后创建的默认备份 : " + originator); }

 

运行可以看到如下结果 : 

  

 以上,使用备忘录的设计模式,好处是显而易见的,我们应该关注的是对象本身具有的(备份/rollback)的行为,而非对象之间的赋值。

 有兴趣的朋友可以看看以上源码 : https://github.com/EalenXie/DesignPatterns 

文章评论

Top