设计模式 笔记9 | 原型模式 在源码中的应用 | ArrayList 中的原型模式 | clone浅克隆 | 基于二进制流的深克隆实现

一、原型模式 知识回顾


原型模式定义: 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
优点;

  • Java 的原型模式是基于内存二进制流数据的复制,在性能上比 new 一个新对象更高
  • 深克隆可保存对象的状态,简化了创建对象的过程

缺点:

  • 需要为每一个类都配置 clone 方法
  • clone 方法位于类的内部,当对已知的类修改时,需修改代码,违背了开闭原则

主要组成:

  • 抽象原型类,规定了具体原型对象必须实现的接口
  • 具体原型类,实现抽象原型类的 clone 方法,是可被复制的对象
  • 访问类,使用具体原型类中的 clone 方法来复制新的对象

分类: 浅克隆 和 深克隆 两种

  • 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,但是对于非基本类型的属性(比如int、float、User 等),仍指向原有属性指向的对象的内存地址
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原来的对象地址

Java 中的 Object 类提供了浅克隆到 clone 方法,具体原型类只要实现 cloneable 接口就可以实现对象的浅克隆。

模板代码:

浅拷贝:直接用等号赋值

public class Demo{
   
    public static void main(String[] args) {
   
        Object a = new Object();
        Object b = a;   // 浅克隆
        System.out.println(a == b);	//  输出结果为 true
    }
}

深拷贝:实现 Cloneable 接口,重写 clone 方法,对于非基本类型的属性需要重新new对象,
Java 自带的 clone 方法实际上是一种浅克隆,只会克隆外层的对象,其内部的对象还是需要手动 new 的

class User implements Cloneable{
   
    String name;
    public User(String name) {
   this.name = name;}

    public String getName() {
   
        return name;
    }

    @Override
    protected User clone() throws CloneNotSupportedException {
   
        User user = (User) super.clone();
        user.name = new String(name);
        return user;
    }
}
public class Demo{
   

    public static void main(String[] args) throws CloneNotSupportedException {
   
        User uni1 = new User("uni");
        User uni2 = uni1.clone();
        System.out.println(uni1 == uni2);	 // false
        System.out.println(uni1.getName() == uni2.getName());	// false
    }
}

应用场景:

  • 对象之间相同或者相似,只有部分几个属性不同
  • 创建对象的成本较大,比如初始化时间长,占用 CPU 太多,或占用网络资源太多等
  • 创建一个对象需要繁琐的数据准备或访问权限等,需提高性能或提高安全性

二、深克隆 与 浅克隆


在 JDK 8 源码中, Clonable 是一个从JDK1.0 出现的没有任何声明方法的空接口,源码如下:

package java.lang;
public interface Cloneable {
   
}

Java 提供 Cloneable 接口的作用:在运行时通知 JVM 可以安全地在该类上使用 clone () 方法,而如果该类没有实现 Clonebale 接口,那么调用 clone 方法则会抛出 CloneNotSupportedException 异常

使用 clone 方法需满足的条件:

  1. 【必选】克隆对象与原型对象不是同一个对象,即对任何对象 o,都有 o.clone() != o
  2. 【必选】克隆对象与原型对象的类型一样,即对任何对象 o, 都有 o.clone().getClass() == o.getClass()
  3. 【可选】对象 o 的 equals () 方法应当满足 o.clone().equals(o) == true 恒成立

基于之前的例子,我们定义了支持深克隆的 User对象,代码如下:

class User implements Cloneable{
   
    String name;
    public User(String name) {
   this.name = name;}

    pu
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值