《23种设计模式之原型模式(2种实现)》

本文探讨了Java中的原型模式,介绍了浅克隆如何仅复制值类型成员变量,以及深克隆如何实现对象及引用类型的完整复制。通过实例演示和总结,揭示了这两种克隆方式的适用场景和优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说在前头:本人为大二在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,能力有限,文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正。若在阅读时有任何的问题,也可通过评论提出,本人将根据自身能力对问题进行一定的解答。 

前言

原型模式是一种对象创建型模式,用原型模式可以用原型实例指定创建对象的种类,它允许通过一个原型对象创建多个同类型的其他对象,而无需知道该对象的创建细节,在Java中可以直接使用Object提供的clone()方法来实现对象的克隆(浅克隆),或使用序列化的方式完成对象的克隆(深克隆)。

浅克隆

浅克隆主要用于对象的复制,要实现浅克隆的类需要具备以下两个条件:

  • 实现Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。

  • 重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。

下面是浅克隆具体的代码实现

package com.bosen.prototype;
​
/**
 * <p>浅克隆</p>
 * @author Bosen 2021/5/25 2:03
 */
public class ShallowPrototype implements Cloneable {
​
    public String param = new String("测试参数");
​
    /*
     * 重写clone方法
     */
    @Override
    public ShallowPrototype clone() {
        ShallowPrototype prototype = null;
        try {
            prototype = (ShallowPrototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }
}
​

测试类

package com.bosen.prototype;
​
import java.io.IOException;
​
/**
 * <p>测试类</p>
 * @author Bosen 2021/5/25 2:14
 */
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ShallowPrototype prototype = new ShallowPrototype();
        ShallowPrototype clone = prototype.clone();
        System.out.println(clone.param == prototype.param);
    }
}
​

运行测试类,输出信息如下

可以得知,原型类与克隆类两者对应的成员变量的内存地址是一样的,也就是说浅克隆时,并未对原型类中的成员变量进行克隆,具体原因是因为原型模式使用浅克隆时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并不会去复制;如果要达到引用对象的克隆我们又该如何去实现呢?我们接下来看看深克隆!

深克隆

深克隆与浅克隆的区别:浅克隆是继承Cloneable接口后重写clone方法完成的克隆,而深克隆需要继承序列化接口Serializable,使类可以序列化,然后将类写入流中再从流中取出完成克隆。

深克隆具体代码:

package com.bosen.prototype;
​
import java.io.*;
​
/**
 * <p>深克隆</p>
 * @author Bosen 2021/5/25 2:18
 */
public class DeepPrototype implements Serializable {
​
    public String param = new String("测试参数");
​
    public Object deepClone() throws IOException, ClassNotFoundException {
        // 将对象写入流中
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
​
        // 将对象从流中取出
        ByteArrayInputStream bai = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bai);
        return ois.readObject();
    }
}
​

测试类:

package com.bosen.prototype;
​
import java.io.IOException;
​
/**
 * <p>测试类</p>
 * @author Bosen 2021/5/25 2:14
 */
public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        DeepPrototype prototype = new DeepPrototype();
        DeepPrototype clone = (DeepPrototype) prototype.deepClone();
        System.out.println(clone.param == prototype.param);
    }
}
​

启动测试类,输出信息如下:

可以看到,此时原型类的成员变量与克隆类的成员变量内存地址不一致了,也就是说他们的这个成员变量不属于同一个对象,成员变量已经完成了克隆。


总结

原型模式的作用:简化了创建对象的过程,通过一个已有的实例进行复制提高了创建实例的效率,具有较好的可扩展性。

浅克隆和深克隆的区别:使用浅克隆时,当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制;而使用深克隆时,除了对象本身被复制外,对象所包含的所有成员变量也将被复制。

原型模式的使用场景:适合于当一个类初始化需要消耗很多资源时,有很多相似对象时,可以设计一个原型,通过对成员变量的些微修改来实现;需要时可以用深克隆的方式保存对象的状态,比如实现撤销操作等。

 👇扫描二维码关注

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云丶言

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

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

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

打赏作者

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

抵扣说明:

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

余额充值