原型模式~

本文详细介绍了原型模式,包括其定义、优缺点、使用场景和注意事项。通过实例展示了如何在Java中实现浅拷贝和深拷贝,以及它们的区别。在汽车工厂的案例中,原型模式用于快速复制汽车对象,以提高性能和减少资源消耗。

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

1. 原型模式

1.1 介绍

指用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。常用于创建某对象的代价比较大时,例如一个对象需要在一个高代价的数据库操作之后被创建。

原型模式的克隆分为浅克隆和深克隆

  • 浅克隆:创建一个新对象,只负责克隆按值传递的数据(比如基本数据类型、String类型),而对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。Java中浅克隆必须实现Cloneable接口
  • 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。深克隆可通过序列化/反序列化,但克隆对象及克隆对象引用的对象必须实现序列化接口

1.2 优缺点

优点

  • 创建对象的性能提高
  • 无需调用构造函数

缺点

  • 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候
  • 必须实现Cloneable接口

1.3 使用场景

  • 资源优化场景,

  • 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等

  • 性能和安全要求的场景。

  • 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

  • 一个对象多个修改者的场景

1.4 注意事项

  • 与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable并重写Clone方法,调用的是底层JNI方法深拷贝是通过实现 Serializable 读取二进制流

2. 案例代码

现在,汽车工厂新建汽车需要多层审批,为了加载建造过程,我们通过复制原有的汽车实现增产。

abstract class CarMat {
    abstract String getName();
}
public class AudiCarMat extends CarMat implements Serializable {
    @Override
    String getName() {
        return "奥迪车垫";
    }
}

abstract class CarWheel {
    abstract String getName();
}
class AudiCarWheel extends CarWheel implements Serializable {
    
    @Override
    String getName() {
        return "奥迪轮子";
    }
}

public class Car implements Cloneable, Serializable {
    CarWheel wheel;
    CarMat mat;

    public void setWheel(CarWheel wheel) {
        this.wheel = wheel;
    }

    public void setMat(CarMat mat) {
        this.mat = mat;
    }

    public CarWheel getWheel() {
        return wheel;
    }

    public CarMat getMat() {
        return mat;
    }

	// 浅拷贝通过JNI实现,要求必须实现Cloneable接口
    public static Car shallowClone(Car car) {
        Car carClone = null;
        try {
            carClone = (Car)car.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return carClone;
    }
    
	// 深拷贝通过序列化实现,要求必须实现Serializable接口
    public static Car deepClone(Car car) {
        ObjectOutputStream oos = null;
        Car carClone = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("temp"));
            oos.writeObject(car);
            oos.flush();
            oos.close();
            
            ObjectInputStream ios = new ObjectInputStream(new FileInputStream("temp"));
            carClone = (Car)ios.readObject();
            ios.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


        return carClone;
    }

}

/**
 * 原型模式
 *
 *@Author cly
 *@Date 2021/08/31 1:24
 *@Version 1.0
 */
public class Prototype {
    public static void main(String[] args) {
        Car car = new Car();
        car.setMat(new AudiCarMat());
        car.setWheel(new AudiCarWheel());
		// 浅拷贝
        Car cloneCar = Car.shallowClone(car);
        System.out.println(car.mat == cloneCar.mat);	//true
        System.out.println(car.wheel == cloneCar.wheel);//true
		// 深拷贝
        Car deepClone = Car.deepClone(car);
        System.out.println(car.mat == deepClone.mat);	// false
        System.out.println(car.wheel == deepClone.wheel);// false
    }
}

3. 源码实现

3.1 java.lang.object

在 JDK 中所有类的默认父类 java.lang.Object 中的 clone 方法,就实现快速地浅拷贝一个对象,当然有个前提条件,就是被克隆的对象的类需要实现 Cloneable 接口,否则会抛出异常 CloneNotSupportedException。

/**
 * Creates and returns a copy of this object.  The precise meaning
 * of "copy" may depend on the class of the object.
 */
protected native Object clone() throws CloneNotSupportedException;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值