设计模式 - 原型模式

原型模式:通过拷贝原型实例,生成一个新的对象(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);
    }
posted @ 2020-11-22 21:55  祁奇  阅读(102)  评论(0编辑  收藏  举报