备忘录模式

Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.

备忘录模式的通用类图

这里写图片描述

备忘录模式的通用源码

  • 发起让人角色

    public class Originator {
    
        private String state;
    
        //备份
        public Memento createMemento() {
            return new Memento(this.state);
        }
    
        //恢复
        public void restoreMemento(Memento memento) {
            this.setState(memento.getState());
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
    }
    
  • 备忘录角色

    public class Memento {
    
        private String state;
    
        public Memento(String state) {
            this.state = state;
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
    }
    
  • 备忘录管理员角色

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

    public class Client {
    
        public static void main(String[] args) {
    
            Originator originator = new Originator();
            Caretaker caretaker = new Caretaker();
    
            originator.createMemento();
            originator.restoreMemento(caretaker.getMemento());
        }
    
    }
    

备忘录模式的使用场景

  • 要保存和恢复数据的相关状态场景。
  • 提供一个可回滚的操作。
  • 需要监控的副本场景中。
  • 数据库连接事务管理。

备忘录模式的注意事项

  • 备忘录的生命周期。备忘录创建出来就要在“最近”的代码中使用,要主动管理他的生命周期,建立就要使用,不用就要立即删除其引用,等待垃圾回收器对其回收。
  • 备忘录的性能。不要在频繁建立备份的场景中使用备忘录模式,比如for循环,因为控制不了备忘录的建立对象的数量,另外他的建立还需要消耗资源。

备忘录模式的简单应用的类图及源码

这里写图片描述

  • 发起角色

    public class Boy {
    
        private String state;
    
        public void changeState() {
            this.state = "心情不好";
        }
    
        //备份
        public Memento createMemento() {
            return new Memento(this.state);
        }
    
        //恢复
        public void restoreMemento(Memento _memento) {
            this.setState(_memento.getState());
        }
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
    }
    
  • 备忘录角色

    public class Memento {
    
        private String state;
    
        public Memento(String state) {
            this.state = state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        public String getState() {
            return state;
        }
    
    }
    
  • 管理备忘录角色

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

    public class Client {
    
        public static void main(String[] args) {
    
            Boy boy = new Boy();
            Caretaker caretaker = new Caretaker();
            boy.setState("心情好");
            System.out.println(boy.getState());
            caretaker.setMemento(boy.createMemento());
            boy.changeState();
            System.out.println(boy.getState());
            boy.restoreMemento(caretaker.getMemento());
            System.out.println(boy.getState());
        }
    }
    

备忘录模式的扩展应用

clone方式的备忘录

这里写图片描述

  • 发起角色

    public class Originator implements Cloneable {
    
        private Originator backup;
        private String state;
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        //备份
        public void createMemento() {
            this.backup = this.clone();
        }
    
        //恢复
        public void restoreMemento() {
            this.setState(this.backup.getState());
        }
    
        @Override
        protected Originator clone() {
            try {
                return (Originator)super.clone();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
    }
    
  • 场景类

    public class Client {
    
        public static void main(String[] args) {
    
            Originator originator = new Originator();
            originator.setState("hao");
            System.out.println(originator.getState());
            originator.createMemento();
            originator.setState("buhao");
            System.out.println(originator.getState());
            originator.restoreMemento();
            System.out.println(originator.getState());
        }
    }
    

注:结合原型模式和备忘录模式,需要考虑原型模式的深拷贝和浅拷贝的问题,在复杂的场景中它会让程序变得逻辑异常混乱,出现错误也很跟踪。

多状态的备忘录模式

这里写图片描述

  • 发起角色

    public class Originator {
    
        private String state1;
        private String state2;
        private String state3;
    
        public String getState1() {
            return state1;
        }
    
        public void setState1(String state1) {
            this.state1 = state1;
        }
    
        public String getState2() {
            return state2;
        }
    
        public void setState2(String state2) {
            this.state2 = state2;
        }
    
        public String getState3() {
            return state3;
        }
    
        public void setState3(String state3) {
            this.state3 = state3;
        }
    
        //备份
        public Memento createMemento() {
            return new Memento(BeanUtils.backupProp(this));
        }
    
        //恢复
        public void restoreMemento(Memento memento) {
            BeanUtils.restoreProp(this, memento.getStateMap());
        }
    
        @Override
        public String toString() {
            return "state1=" + state1 + "\nstate2=" + state2 + "\nstate3=" + state3;
        }
    
    }
    
  • 备忘录角色

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

    import java.beans.BeanInfo;
    import java.beans.Introspector;
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    
    public class BeanUtils {
    
        //把bean所有的属性及数值放入到HashMap中
        public static HashMap<String, Object> backupProp(Object bean) {
            HashMap<String, Object> result = new HashMap<String, Object>();
            try {
                //获得Bean描述
                BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
                //获得属性描述
                PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
                //遍历所有属性
                for(PropertyDescriptor descriptor : descriptors) {
                    //属性名称
                    String fieldName = descriptor.getName();
                    //读取属性的方法
                    Method getter = descriptor.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) {
            try {
                //获得Bean描述
                BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
                //获得属性描述
                PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
                //遍历所有属性
                for(PropertyDescriptor descriptor : descriptors) {
                    //属性名称
                    String fieldName = descriptor.getName();
                    //如果有这个属性
                    if (propMap.containsKey(fieldName)) {
                        //写属性的方法
                        Method setter = descriptor.getWriteMethod();
                        setter.invoke(bean, new Object[]{propMap.get(fieldName)});
                    }
                }
            } catch (Exception e) {
                System.out.println("shit");
                e.printStackTrace();
            }
        }
    
    }
    
  • 场景类

    public class Client {
    
        public static void main(String[] args) {
    
            Originator originator = new Originator();
            originator.setState1("111");
            originator.setState2("222");
            originator.setState3("333");
            System.out.println(originator.toString());
            Memento memento = originator.createMemento();
            originator.setState1("qqq");
            originator.setState2("www");
            originator.setState3("eee");
            System.out.println(originator.toString());
            originator.restoreMemento(memento);
            System.out.println(originator.toString());
        }
    }
    

注:备份了很多属性,但是没有实现多备份的备忘录,接下来讲解多备份的备忘录模式

多备份的备忘录

在上述的示例中实现多备份,只需要增加备忘录管理员角色的源码和修改对应的场景类。

  • 增加的备忘录管理员角色

    public class Caretaker {
    
        //容纳备忘录的容器
        private HashMap<String, Memento> mementoMap = new HashMap<String, Memento>();
    
        public HashMap<String, Memento> getMementoMap() {
            return mementoMap;
        }
    
        public void setMementoMap(HashMap<String, Memento> mementoMap) {
            this.mementoMap = mementoMap;
        }
    }       
    
  • 修改的场景类

    public class Client1 {
    
        public static void main(String[] args) {
    
            //定义出发人
            Originator originator = new Originator();
            Caretaker caretaker = new Caretaker();
            //创建备忘录
            caretaker.setMemento("111", originator.createMemento());
            caretaker.setMemento("222", originator.createMemento());
            //恢复一个指定标记的备忘录
            originator.restoreMemento(caretaker.getMemento("111"));
        }
    
    }                   
    

封装得更好一点

在系统管理上,一个备份的数据是完全、绝对不能修改的,它保证数据的洁净,避免数据污染而使备份失去意义。备份是不能被篡改的,也就是说需要缩小备份出的备忘录的阅读权限,保证发起人可读就OK了。

这里写图片描述

  • 发起人角色

    public class Originator {
    
        private String state = "";
    
        public String getState() {
            return state;
        }
    
        public void setState(String state) {
            this.state = state;
        }
    
        //备份
        public IMemento createMemento() {
            return new Memento(this.state);
        }
    
        //恢复
        public void restoreMemento(IMemento memento) {
            this.setState(((Memento)memento).getState());
        }
    
        //内部类
        private class Memento implements IMemento {
            //发起人的内部状态
            private String state = "";
            //构造函数传递参数
            private Memento(String state) {
                this.state = state;
            }
            private String getState() {
                return state;
            }
            private void setState(String state) {
                this.state = state;
            }
        }
    
    }
    
  • 备忘录接口

    public interface IMemento {
    
    }
    
  • 管理备份录角色

    public class Caretaker {
    
        private IMemento memento;
    
        public IMemento getMemento() {
            return memento;
        }
    
        public void setMemento(IMemento memento) {
            this.memento = memento;
        }
    }
    
  • 场景类

    public class Client {
    
        public static void main(String[] args) {
    
            Originator originator = new Originator();
            Caretaker caretaker = new Caretaker();
    
            originator.setState("hello");
            System.out.println(originator.getState());
            originator.createMemento();
            originator.setState("wellow");
            System.out.println(originator.getState());
            originator.restoreMemento(caretaker.getMemento());
            System.out.println(originator.getState());
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼王呵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值