美文网首页
设计模式之备忘录模式.

设计模式之备忘录模式.

作者: 北风一叶 | 来源:发表于2016-02-07 05:37 被阅读239次

    本文是对设计模式之禅一书中备忘录模式一章的总结与整理。

    1. 定义

    在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将对象恢复到原先保存的的状态,我就不明月了,为啥这些大师总喜欢将定义写的这么复杂呢,我看极有可能是自己的水平没那个份上,这个定义写成接地气的话就是“在操作一个对象前,把这个对象临时保存一份,以便将来恢复,相当于是后悔药。”通用类图如下:

    通用类图.png
    1. Originator 发起人角色:记录当前时刻的内部状态,负责定义哪些属于备份的状态,负责创建和恢复备忘录数据。
    1. Memento 备忘录角色:负责存储Originator发起人对象的内部状态 ,在需要的时候提供发起人需要的内部状态
    1. Caretaker备忘录管理员角色:对备忘录进行管理、保存和提供备忘录

    书中说这类标准的模很难在项目中遇到,基本者是变换后的处理方式,所以此处不再提供示例。

    2. 扩展

    第一种:Clone方式的备忘录

    通过复制的方式产生一个对象的内部状态,类图如下:

    类图1.png

    发起人:

    
    public class Originator implements Cloneable {
        private Originator backup;
        //内部状态
        private String state="";
        public String getState(){
            return this.state;
        }
        public void setState(String _state){
            this.state=_state;
        }
    
        //创建备忘录
        public void createMemento(){
            this.backup =  this.clone();
        }
    
        //克隆当前对象
        @Override
        protected Originator clone(){
            try {
                return (Originator)super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        //恢复备忘录
        public void restoreMemento(){
            this.setState(this.backup.getState());
        }
    }
    

    备忘录管理者

    
    public class Caretaker {
        //发起人对象
        private Originator originator;
    
        public Originator getOriginator(){
            return  this.originator;
        }
    
        public void setOriginator(Originator _originator){
            this.originator=_originator;
        }
    
    
    }
    

    场景类:

    
    public class Client {
        public static void main(String[] strings) {
            Originator originator = new Originator();
            //初始状态
            originator.setState("初始状态.....");
            System.out.println("初始状态是:"+originator.getState());
            //备份
            originator.createMemento();
            //修改状态
            originator.setState("修改状态....");
            System.out.println("修改后的状态为:"+originator.getState());
            //恢复状态
            originator.restoreMemento();
            System.out.println("恢复后的状态为:"+originator.getState());
        }
    }
    

    运行结果如下:

    结果1.png
    第二类:多状态的备忘录模式

    第一种情况中只一种状态,如果有多种状态就采用这种方式,通用类图如下:

    类图2.png

    再来看代码,发起人:

    
    public class Originator implements Cloneable {
    
        //内部状态
        private String state1="";
    
        public String getState2() {
            return state2;
        }
    
        public void setState2(String state2) {
            this.state2 = state2;
        }
    
        public String getState1() {
            return state1;
        }
    
        public void setState1(String state1) {
            this.state1 = state1;
        }
    
        public String getState3() {
            return state3;
        }
    
        public void setState3(String state3) {
            this.state3 = state3;
        }
    
        private String state2="";
        private String state3="";
    
    
    
        //创建备忘录
        public Memento createMemento(){
            return new Memento(BeanUtils.backupProps(this));
        }
        //恢复备忘录
        public void restoreMemento(Memento _memento){
           BeanUtils.restoreProps(this,_memento.getStateMap());
        }
    
        //toString
    
    
        @Override
        public String toString() {
            return "state1="+state1+",state2="+state2+",state3="+state3;
        }
    }
    

    备忘录如下:

    
    public class Memento {
        public HashMap<String, Object> getStateMap() {
            return stateMap;
        }
    
        public void setStateMap(HashMap<String, Object> stateMap) {
            this.stateMap = stateMap;
        }
    
        //接爱HashMap作为状态
        private HashMap<String,Object> stateMap;
        //接受一个对象,建立备份
        public Memento(HashMap<String,Object> map){
            this.stateMap=map;
        }
    
    }
    

    工具类:

    
    public class BeanUtils {
        public static HashMap<String,Object> backupProps(Object bean){
            HashMap<String,Object> result=new HashMap<>();
            try {
                //获取属性描述
                BeanInfo beanInfo= Introspector.getBeanInfo(bean.getClass());
                //获得属性
                PropertyDescriptor[] descriptors=beanInfo.getPropertyDescriptors();
                //遍历
                for(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 ex){
    
            }
            return  result;
        }
    
        public static void restoreProps(Object bean,HashMap<String,Object> propMap){
            //获取属性描述
            BeanInfo beanInfo= null;
            try {
                beanInfo = Introspector.getBeanInfo(bean.getClass());
                //获得属性
                PropertyDescriptor[] descriptors=beanInfo.getPropertyDescriptors();
                for(PropertyDescriptor des:descriptors){
                    String fieldName=des.getName();
                    if(propMap.containsKey(fieldName)){
                        Method setter=des.getWriteMethod();
                        setter.invoke(bean,new Object[]{propMap.get(fieldName)});
                    }
                }
            } catch (Exception e) {
                System.out.println("shit");
                e.printStackTrace();
            }
    
        }
    }
    

    备忘录管理员角色:

    
    public class Caretaker {
        public Memento getMemento() {
            return memento;
        }
    
        public void setMemento(Memento memento) {
            this.memento = memento;
        }
    
        private Memento memento;
    
    
    
    }
    

    场景类:

    
    public class Client {
        public static void main(String[] strings){
           Originator originator=new Originator();
    
            originator.setState1("中国");
            originator.setState2("强盛");
            originator.setState3("繁荣");
            System.out.println("初始状态:"+originator.toString());
            //创建一个备忘录
            Caretaker caretaker=new Caretaker();
            caretaker.setMemento(originator.createMemento());
            originator.setState1("软件");
            originator.setState3("架构");
            originator.setState2("优秀");
            System.out.println("后状态:"+originator.toString());
    
            originator.restoreMemento(caretaker.getMemento());
    
            System.out.println("原状态:"+originator.toString());
        }
    }
    

    运行结果如下:

    结果2.png
    第三种情况是多备份,就是有多个备份的情况,再看备忘录管理员角色如下:
    
    public class Caretaker {
    
        //创建一个容器
        private HashMap<String, Memento> mementoHashMap = new HashMap<>();
    
        public Memento getMemento(String idx) {
            return mementoHashMap.get(idx);
        }
    
        public void setMementoHashMap(String idx, Memento memento) {
            this.mementoHashMap.put(idx, memento);
        }
    }
    ``
    
    再来看场景类如下:
    
    ```java
    
    public class Client {
        public static void main(String[] strings){
           Originator originator=new Originator();
    
            originator.setState1("中国");
            originator.setState2("强盛");
            originator.setState3("繁荣");
            System.out.println("初始状态:"+originator.toString());
            //创建一个备忘录
            Caretaker caretaker=new Caretaker();
            //创建两个备份
            caretaker.setMementoHashMap("001",originator.createMemento());
            caretaker.setMementoHashMap("002",originator.createMemento());
           
            originator.setState1("软件");
            originator.setState3("架构");
            originator.setState2("优秀");
            System.out.println("后状态:"+originator.toString());
            //恢复一份备份
            originator.restoreMemento(caretaker.getMemento("001"));
    
            System.out.println("原状态:"+originator.toString());
        }
    }
    

    结果就不上了。

    3.结论

    备忘录模式,严格来讲是一个比较简单的模式,可以把它理解成一个临时表的作用,当临时表使,只是它的变化形式比较多而已,但我认为记住以上的这三种情况就足够用了。

    注:本方代码段比较多,莫怪。

    相关文章

      网友评论

          本文标题:设计模式之备忘录模式.

          本文链接:https://www.haomeiwen.com/subject/nodykttx.html