Java设计模式之原型模式(浅克隆,深克隆)

一、原型模式:

  1. 概述:

创建型模式之一,它通过复制一个已有对象来获取更多相同或相似的对象,可提高对象创建效率,简化创建过程。

  1. 原理:

将一个原型对象传给要发动创建的对象(如客户端对象),这个客户端对象通过请求原型对象复制自己来实现创建过程。

二、原型模式结构:

  1. Prototype:抽象原型类
  2. ConcretePrototype:具体原型类
  3. Client:客户端类

三、浅克隆与深克隆:

关注成员变量是值类型还是引用类型,在深浅克隆中是如何复制这些变量。

  1. 浅克隆:

原型对象的成员变量是值类型,则将复制一份给克隆对象。但如果是成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的引用类型变量指向同一个内存地址

在这里插入图片描述

  1. 深克隆:

无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。也就是说,除了对象本身被复制外,对象所有的成员变量也将被复制。

在这里插入图片描述

四、实现:

在Java语言中,所有的Java类均继承自Java.lang.Object类,Object类提供了一个clone()方法,可以用来实现对象的浅克隆

  1. 派生类实现Cloneable接口,在派生类中覆盖基类的clone方法,并声明为public。
  2. 派生类的clone()方法中调用super.clone()。

此时,Object类相当于抽象原型类,所有实现了Cloneable接口的类相当于具体实现类。

注:
(1)克隆对象与原型对象不是同一个对象
(2)克隆对象与原型对象的类型一样
(3)如果对象x的equals方法定义恰当,那么x.clone().equals(x)应该成立。


Java深克隆可通过序列化的方式来实现。

序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个复制,而原对象仍然在内存中。通过序列化实现的复制,不仅可以复制对象本身,而且可以复制其引用的成员对象。因此,通过序列化将对象写到一个流中,再从流中将其读取出来,可以实现深克隆。

  1. 实现Serializable接口。
  2. 将对象写入流中,将对象从流中读取。

五、应用案例:

在这里插入图片描述

分析:复制新的周报,每个周报对象不相同,但里面的附件需一样。即实现周报的浅克隆。

  1. 创建附件类Attachment。
public class Attachment {
    private String name;
	//getter,setter方法省略
    public void download(){
        System.out.println("下载附加,文件名为:"+name);
    }
}
  1. 创建周报类WeeklyLog,包含附件类,实现Cloneable。
package Prototype.demo1;

public class WeeklyLog implements Cloneable{
	//引用对象类
    private Attachment attachment;
    private String name;
    private String date;
    private String content;
    //getter,setter方法省略
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

  1. 客户端client。
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        WeeklyLog log_pre,log_new;
        log_pre=new WeeklyLog();
        Attachment attachment=new Attachment();
        log_pre.setAttachment(attachment);
        //Java自带克隆机制
        log_new= (WeeklyLog) log_pre.clone();
        //判断是否实现了浅克隆
        System.out.println("周报是否相同:"+(log_pre==log_new));
        System.out.println("附件是否相同:"+(log_pre.getAttachment()==log_new.getAttachment()));
    }
}
  1. 测试运行:

在这里插入图片描述

分析:如目前需要将附件也一同拷贝到周报中,可使用序列化,对周报对象进行深拷贝。此时,WeeklyLog类不再使用Java自带的克隆机制,而是通过序列化从头实现对象的深克隆。

  1. 附件类,周报类实现Serializable接口。
  2. 周报类编写深克隆方法。
//采用序列化技术实现深克隆
    public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
    	//将对象写入到流中
        ByteArrayOutputStream bao=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bao);
        oos.writeObject(this);
		
		//将对象从流中取出
        ByteArrayInputStream  bis=new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);

        return (WeeklyLog)ois.readObject();

    }
  1. 测试运行:

在这里插入图片描述

六、总结:

(1)通过复制一个已有的对象来来获取更多相同或者相似的对象。
(2)浅克隆可以使用Java自带的克隆方法,深克隆可以通过实现序列化接口,将对象写入流中,再从流中进行读取的方法实现。
(3)浅克隆:只复制值类型变量,引用类型不复制,只复制其内存地址。深克隆:值类型,引用类型变量都复制。
(4)适用情况:创建新对象的成本大(例如初始化时间长,占用CPU资源等);系统要保存对象的状态,而对象的状态变化很小;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT学习小镇

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

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

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

打赏作者

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

抵扣说明:

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

余额充值