Java设计模式(原型设计模式)

原型设计模式(创建型模式)

用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象,且无需知道如何创建的细节。
适用于创建复杂的或者构建耗时的对象,通过原型拷贝效率高效。

如图所示,浅拷贝案例,实现 Cloneable接口,重写Object类下的clone()方法完成克隆。
在这里插入图片描述
创建对象花费2000多毫秒,克隆几乎没有花费时间,说明克隆不走构造函数
克隆的对象 hashCode 与 原来的对象不一样,说明产生了一个新的对象,并且把原有的属性值也赋值给克隆对象。(赋值实际是将引用地址赋值)
在这里插入图片描述


这里就谈谈 浅拷贝 深拷贝

浅拷贝

需要拷贝了类,必需实现Cloneable接口,因为Object.clone()是protected,所以需要重写,才能调用。
会在内存中新开辟一个空间,存放拷贝后的对象,且属性会继续引用拷贝前的内存地址。

在 User 类中新加一个 Employee 引用属性
在这里插入图片描述

浅拷贝,只是重新建立了一个对象,但之前的引用属性内存地址都没有发生变化,修改克隆类里的 Employee里的属性,之前的对象也会发生改变。
但是修改 String 类型的数据,之前的对象不会发生改变,因为String类有 final 修饰符;
在这里插入图片描述

深拷贝

为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝

Employee 也实现 Cloneable接口,重写 clone() 方法
在这里插入图片描述

User 类的 clone() 对User拷贝后,再设置 employee引用对象也调用克隆方法
在这里插入图片描述

运行结果,引用对象的 employee就是一个新的对象,新的内存地址。

在这里插入图片描述

以上是 重写clone方法来实现深拷贝,就是需要拷贝的对象,所有的引用对象属性的类,都需要重写克隆方法,且拷贝对象的引用对象的属性都需要调用克隆方法赋值,这样的方式缺点,如果引用对象属性很多,则都需要调用clone方法赋值,很是繁琐。



通过对象序列化实现深拷贝 类必需实现 Serializable 接口,不然序列化会报错

public class Test {

    public static void main(String[] args) throws Exception {
        User user = new User("张三", "男");
        System.out.println("拷贝前:user.employee " + user.getEmployee());
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;

        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);

            /* 写入 user 对象 */
            oos.writeObject(user);

            bais = new ByteArrayInputStream(baos.toByteArray());
            ois = new ObjectInputStream(bais);

            /* 读取 user 对象 */
            User clone = (User) ois.readObject();

            clone.getEmployee().setNickname("经理");  // 为拷贝后的对象的 Employee.nickname 重新赋值
            clone.setName("李四");                    // 为拷贝后的对象的 name 重新赋值
            System.out.println("user " + user);
            System.out.println("user.employee.hashCode  " + user.getEmployee().hashCode());
            System.out.println("user.employee " + user.getEmployee());
            System.out.println("clone " + clone);
            System.out.println("clone.employee.hashCode " + clone.getEmployee().hashCode());
            System.out.println("clone.employee " + clone.getEmployee());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                baos.close();
            }
            if (oos != null) {
                oos.close();
            }
            if (bais != null) {
                bais.close();
            }
            if (ois != null) {
                ois.close();
            }
        }

    }

}

运行结果;产生的是新对象,引用对象属性也是新的对象;
在这里插入图片描述
通过对象序列化实现深拷贝,可以减少频繁的调用 clone 方法进行克隆,减小了开发成本。


觉得对您有帮助,就点个赞呗。😀
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Me_Liu_Q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值