• 《设计模式之禅》--备忘录扩展:多状态的备忘录


    接上篇《设计模式之禅》--备忘录扩展:clone方式的备忘录

    需求:对象全状态备份方案

    发起人

    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());
        }
    
        //增加一个toString方法
        @Override
        public String toString() {
            return "state1=" + state1 + "
    stat2=" + state2 + "
    state3=" + state3;
        }
    }

    BeanUtils工具类

    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 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) {
                //异常处理
            }
            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 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 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;
        }
    }

    调用

    public class Client {
        public static void main(String[] args) {
            //定义出发起人
            Originator ori = new Originator();
            //定义出备忘录管理员
            Caretaker caretaker = new Caretaker();
            //初始化
            ori.setState1("中国");
            ori.setState2("强盛");
            ori.setState3("繁荣");
            System.out.println("===初始化状态===
    " + ori);
            //创建一个备忘录
            caretaker.setMemento(ori.createMemento());
            //修改状态值
            ori.setState1("软件");
            ori.setState2("架构");
            ori.setState3("优秀");
            System.out.println("
    ===修改后状态===
    " + ori);
            //恢复一个备忘录
            ori.restoreMemento(caretaker.getMemento());
            System.out.println("
    ===恢复后状态===
    " + ori);
        }
    }

    结果

    ===初始化状态===
    state1=中国
    stat2=强盛
    state3=繁荣
    ===修改后状态===
    state1=软件
    stat2=架构
    state3=优秀
    ===恢复后状态===
    state1=中国
    stat2=强盛
    state3=繁荣

    注意

    如果要设计一个在运行期决定备份状态的框架,则建议采用AOP框架来实现,避免采用动态代理无谓地增加程序逻辑复杂性

    再扩展:

    需求:多备份的备忘录

    public class Caretaker {
        //容纳备忘录的容器
        private HashMap<String, Memento> memMap = new HashMap<String, Memento>();
    
        public Memento getMemento(String idx) {
            return memMap.get(idx);
        }
    
        public void setMemento(String idx, Memento memento) {
            this.memMap.put(idx, memento);
        }
    }

    调用

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

    注意

    内存溢出问题,该备份一旦产生就装入内存,没有任何销毁的意向,这是非常危险的。因此,在系统设计时,要严格限定备忘录的创建,建议增加Map的上限,否则系统很容易产生内存溢出情况

    再扩展

    需求:权限设为发起人可读

    发起人角色

    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;
        }
    }

    在这里我们使用了一个新的设计方法:双接口设计,我们的一个类可以实现多个接口,在系统设计时,如果考虑对象的安全问题,则可以提供两个接口,一个是业务的正常接口,实现必要的业务逻辑,叫做宽接口;另外一个接口是一个空接口,什么方法都没有,其目的是提供给子系统外的模块访问,比如容器对象,这个叫做窄接口,由于窄接口中没有提供任何操纵数据的方法,因此相对来说比较安全。

  • 相关阅读:
    外设简述
    代C语言上机实践
    css动画效果
    css滑动门原理
    css整理
    html
    html单词
    倒计时.js
    随机方块
    求字符串出现次数和最大值
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/8444127.html
Copyright © 2020-2023  润新知