设计模式(十八)---备忘录模式

来源:互联网 发布:移魂都市知乎 编辑:程序博客网 时间:2024/05/30 02:25
 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将

  该对象恢复到原先保存的状态。

一般模式:

 
  Originator发起人角色
   ---|记录当前时刻的内部状态,负责定义那些属于备份范围的状态,负责创建和恢复备忘录数据
  Memento备忘录角色
   ---|负责存储Originator发起人对象的内部状态,在需要的时候提供发起人需要的内部状态
  Caretaker备忘录管理员角色

   ---|对备忘录进行管理、保存和提供备忘录。

public class MementoTest {public static void main(String[] args) {//定义一个备忘录的发起者Originator origin = new Originator();origin.setState("你好!");//定义一个备忘录的管理者Caretaker care = new Caretaker();//创建一个备忘录care.setMemento(origin.createMemento());origin.setState("去死吧!");//恢复原有的数据origin.restoreMemento(care.getMemento());System.out.println(origin.getState());}}/** * 备忘录发起人的角色, * 备忘录中保存的就是该类的内容。 * @author admin * */class Originator{//一个String类型表示当前状态private String state = "";public String getState() {return state;}public void setState(String state) {this.state = state;}//创建一个备忘录角色,用于时刻存储数据。public Memento createMemento(){return new Memento(this.state);}//回复原来的数据public void restoreMemento(Memento memento){this.setState(memento.getState());}}/** * 备忘录角色, * 该类用于备份、存储原有数据。 * @author admin * */class Memento{//一个String类型表示当前状态private String state = "";public Memento(String state) {this.state = state;}public String getState() {return state;}public void setState(String state) {this.state = state;}}/** * 备忘录的管理类 * 对备忘录进行管理、保存和存储 * @author admin */class Caretaker{private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}}

 一个例子:

   模拟月光宝盒中,至尊宝阻止白晶晶自杀的桥段。当白晶晶在洞内自杀,至尊宝没有来得及救,于是就使用月光宝盒--菠萝菠萝蜜
   任何就回到上一个状态,继续去救白晶晶,知道能够成功救到为止。
   这个例子可以说明,救白晶晶之前,首先保存一个状态命名为1,从这一状态出发,如果没有成功,就回到1状态。

public class MementoT {public static void main(String[] args) {//创建一个发起者,(看见白晶晶在自杀)SaveLifeAction action = new SaveLifeAction();action.setState("白晶晶被至尊宝伤透了心...准备拿剑抹脖子自杀");//月关宝盒时刻记录每一瞬间BoxManager boxManager = new BoxManager();boxManager.setBoxMemento(action.createMemento());action.setState("白晶晶自杀死了...");System.out.println(action.getState());System.out.println("---至尊宝拿着月关宝盒,回去救她----");//至尊宝拿着月关宝盒,回去救她action.restoreMemento(boxManager.getBoxMemento());//回到上一状态System.out.println(action.getState());action.setSuccess(true);if(action.isSuccess()){System.out.println("----白晶晶成功获救!");}}}/** * 该类是发起者类, * 设置负责创建和恢复备忘录 * @author admin * */class SaveLifeAction{//定义一个状态,用于描述当前正在做什么..private String  state="";//设置是否救成功private boolean isSuccess;public String getState() {return state;}public void setState(String state) {this.state = state;}public boolean isSuccess() {return isSuccess;}public void setSuccess(boolean isSuccess) {this.isSuccess = isSuccess;}//创建一个备份的状态public BoxMemento createMemento(){return new BoxMemento(this.state);}//恢复到原来的状态public void restoreMemento(BoxMemento boxMemento){this.setState(boxMemento.getState());}}/** * 该类是备忘录类 * 相当于故事中的月光宝盒,他带你回到上一个状态。 * 内部实现的原理就是,保存上一状态而已。 * @author admin * */class BoxMemento{private String state="";public BoxMemento(String state) {this.state = state;}public String getState() {return state;}public void setState(String state) {this.state = state;}}/** * 备忘录的管理者, * 谁拿到月光宝盒,谁就可以操纵月光宝盒, * 就可以回到过去。 * @author admin * */class BoxManager{private BoxMemento boxMemento;public BoxMemento getBoxMemento() {return boxMemento;}public void setBoxMemento(BoxMemento boxMemento) {this.boxMemento = boxMemento;}}
备忘录模式的使用场景
   ---|需要保存和恢复数据的相关状态场景。
   ---|提供一个可回滚(rollback)的操作,比如word中Ctrl+Z的组合键。
   ---|需要监控的副本场景中。
   ---|数据库连接的事务管理就是用的备忘录模式。

备忘录的扩展

 ---|1、实现java类中的Cloneable实现备忘录模式
      使用clone方式的备忘录模式,可以使用在比较简单的场景或者比较单一的场景中,
      尽量不要与其他的对象产生严重的耦合关系。

public class MementoExpand {public static void main(String[] args) {//定义一个发起人OriginClass origin = new OriginClass();origin.setState("我的原始状态");//创建备份origin.createOrigin();origin.setState("我的现在状态..");System.out.println(origin.getState());System.out.println("------我不喜欢现在的状态-------");//恢复原来的状态origin.restoreOrigin();System.out.println(origin.getState());}}/** * 发起者实现Cloneable接口,完成自身的备忘录设置。 * 无需接触其他类来保存自身的当前状态。 * @author admin * */class OriginClass implements Cloneable{private String state;//自身的备忘录角色private OriginClass backUp;public String getState() {return state;}public void setState(String state) {this.state = state;}//创建备份public void createOrigin(){this.backUp = (OriginClass) this.clone();}//恢复原来的信息public void restoreOrigin(){this.setState(backUp.getState());}@Overrideprotected Object clone() {try {return (OriginClass) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}}

   ---|2多状态的备忘录模式

/** * 通过java.beans.Introspector类获取其他类中的属性和方法 * @author admin * */public class BeanUtil {public static void main(String[] args) {//创建一个发起者MyOringin origin = new MyOringin("lzl",10000,"程序员");System.out.println("在百度公司里:"+origin.toString());//在百度公司创建备份MyMementor mementor = origin.createMemento();System.out.println("感觉太累了,跳槽的阿里巴巴...");origin.setName("lzl");origin.setPosition("程序员");origin.setSalary(12000);System.out.println("跳槽到阿里:"+origin.toString());System.out.println("----------------在这里更累,跟着老大,10天没合眼...想回到百度了.");origin.restoreMemento(mementor);System.out.println("回到百度,还是很轻松的。。"+origin.toString());}//获取发起者类中的属性参数,并保存在hashMap中public static HashMap<String, Object> backUpProp(Object bean){HashMap<String, Object> result = new HashMap<String, Object>();//获得Bean描述try {BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());//返回PropertyDescriptor类型的javaBean描述PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();//遍历返回的javaBeanfor(PropertyDescriptor des : descriptors){String fieldName = des.getName();//读取属性的方法Method getter = des.getReadMethod();//读取属性值Object fieldValue = getter.invoke(bean, new Object[]{});if(!fieldName.equalsIgnoreCase("class")){result.put(fieldName, fieldValue);}}} catch (Exception e) {e.printStackTrace();}return result;}//把HashMap中的值设置到bean中。public static void restoreProp(Object bean,HashMap<String, Object> propMap){//获取BeanInfotry {BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());//获取PropertyDescriptor的对象数组PropertyDescriptor[] descripors = beanInfo.getPropertyDescriptors();//增强for循环,遍历所有的属性,设置到bean中for(PropertyDescriptor des : descripors){//获取key值对象String fieldName = des.getName();//如果包含这个属性if(propMap.containsKey(fieldName)){//获取属性set的方法Method setter = des.getWriteMethod();setter.invoke(bean, new Object[]{propMap.get(fieldName)});}}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/** * 类的发起者,模拟拥有多个属性。 * @author admin * */class MyOringin{//姓名private String name;//薪水private double salary;//职位private String position;public MyOringin(String name,double salary,String position) {this.name = name;this.salary = salary;this.position = position;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}public String getPosition() {return position;}public void setPosition(String position) {this.position = position;}//创建一个备份public MyMementor createMemento(){//将方法属性存储到BeanUtil.backUpProp()中的hashMap中return new MyMementor(BeanUtil.backUpProp(this));}public void restoreMemento(MyMementor memento){BeanUtil.restoreProp(this, memento.getBeanMap());}@Overridepublic String toString() {return "姓名:"+this.name+"\t职位:"+this.position+"\t薪水:"+this.salary+"\t";}}/** * 备忘录类,用于保存原有的状态。 * @author admin */class MyMementor{//定义一个hashMap来接收发起者的所有属性状态备份private HashMap<String, Object> beanMap = new HashMap<String, Object>();public MyMementor(HashMap<String, Object> beanMap) {this.beanMap = beanMap;}public HashMap<String, Object> getBeanMap() {return this.beanMap;}public void setBeanMap(HashMap<String, Object> beanMap) {this.beanMap = beanMap;}}

0 0
原创粉丝点击