zoukankan      html  css  js  c++  java
  • 设计模式 原型模式

    原型模式:通过拷贝原型实例,生成一个新的对象(java中,多专指实现Cloneable接口对象)

    实现原理:

    • clone的实现是在内存中直接拷贝二进制流,无需经过构造函数(native方法,上帝后门)。
    • 通过cloneable接口标记对象是否有权触发object.clone()方法。

    优点:

    • clone方法直接操作内存拷贝二进制流,性能优越。
    • 不需要经过构造函数等,避免了构造函数中的约束。

    应用场景:

    • 性能和资源优化:类初始化需要消费非常多资源,在需要创建大量重复的类时。
    • 跳过校验的场景:当创建类需要做非常繁琐的数据准备和检验时。
    • 对象需要被分享时:一个对象被多个访问者同时访问时,通过拷贝避免共享干扰。

    浅复制:clone方法是对内存中的二进制流做复制,所以,当对象属性中存在引用对象时,只复制引用

    clone的一般实现

    浅克隆(Cloneable)

        // java自带cloneable接口浅克隆 - 通过内存二进制流复制实现
        @Override
        public PrototypeMember clone(){
            try {
                return (PrototypeMember)super.clone();
            } catch (CloneNotSupportedException e){
                e.printStackTrace();
                return null;
            }
        }
    

    深克隆(Cloneable)

        // java自带cloneable,通过递归将所有引用属性都进行clone后实现深克隆
        public PrototypeMember deepcloneByCloneable(){
            try {
                PrototypeMember prototypeMember = (PrototypeMember)super.clone();
                // java为集合中大部分的实现类提供了clone方法的浅复制实现
                prototypeMember.list = (List)((ArrayList)list).clone();
                return prototypeMember;
            } catch (CloneNotSupportedException e){
                e.printStackTrace();
                return null;
            }
        }
    

    扩展 - 序列化实现深克隆(Serializable)

    1. 只有实现了Serializable接口的类才可以序列化和反序列化
    2. 反序列化时:会在继承链中,找到离实际对象最近的一个没有实现Serializable接口的父类,并调用其构造方法
    • 实际的创建过程应该是 未实现Serializable接口的父类的构造方法实现了Serializable接口的子类的ObjectStreamClass(描述了class对象结构),一同完成对象的创建。
        // java自带Serializable,通过obj序列化成字节数组,再反序列实现clone
        public PrototypeMember deepCloneBySerializable(){
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(this);
    
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bis);
                return (PrototypeMember) ois.readObject();
            } catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
    

    扩展 - 反射复制

    • json的实现方法即为反射,需要调用对象类的构造函数(所以性能并没有提升)
        // 使用反射完成clone浅克隆
        public PrototypeMember cloneByReflect(){
            try {
                Class clazz = this.getClass();
                PrototypeMember result = (PrototypeMember)clazz.newInstance();
                for(Field filed : clazz.getDeclaredFields()){
                    filed.setAccessible(true);
                    filed.set(result,filed.get(this));
                }
                return result;
            } catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
    
        // 使用json实现深克隆
        public PrototypeMember deepCloneByJSON(){
            String json = JSONObject.toJSONString(this);
            return JSON.parseObject(json,PrototypeMember.class);
        }
    
  • 相关阅读:
    codeforce 266c Below the Diagonal 矩阵变换 (思维题)
    8月21日训练日记
    CodeForces 651B Beautiful Paintings
    CodeForces 651 C Watchmen
    CodeForces 17D Notepad(同余定理)
    CodeForces 19B Checkout Assistant
    Code Forces 18D Seller Bob(简单DP)
    HOJ Recoup Traveling Expenses(最长递减子序列变形)
    ZOJ 3469Food Delivery(区间DP)
    Code Forces 149DColoring Brackets(区间DP)
  • 原文地址:https://www.cnblogs.com/kiqi/p/14021746.html
Copyright © 2011-2022 走看看