定义
浅拷贝是指在拷贝对象时,只复制对象本身以及对象中的基本数据类型字段,而不复制引用类型字段。因此,浅拷贝产生的新对象和原对象共享引用类型字段的内容。
代码
//地址
class Address {
private String city;
public Address(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
//人
class Person implements Cloneable {
private Integer age;
private String name;
private Address address;
public Person(Integer age, String name, Address address) {
this.age = age;
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() {
return address;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ShallowCopyPrototypeExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address originalAddress = new Address("广州");
Person originalPerson = new Person(18, "John", originalAddress);
// 浅拷贝
Person clonedPerson = (Person) originalPerson.clone();
// 修改拷贝对象的值
clonedPerson.setAge(20);
clonedPerson.setName("Jane");
clonedPerson.getAddress().setCity("深圳");
// 输出原来对象的值
System.out.println("Original Person Age: " + originalPerson.getAge()); // Output: 18
System.out.println("Original Person Name: " + originalPerson.getName()); // Output: John
System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity()); // Output: 深圳
}
}
通过上面的代码输出,我们可以看到Age还是原来的18,说明基本对象是重新复制了一个,但是Address变成了我们修改后的值,可以证明他们是同一个引用的。
而至于为什么 String 类型没有变化,大家可以看我另外一个文章new String()创建了几个对象?,由于Java中 String 对象的不可变性,对 String 对象进行修改实际上是创建了一个新的 String 对象,而原来的对象保持不变。
定义
深拷贝是指在拷贝对象时,不仅复制对象本身,还复制对象中引用类型字段所指向的对象,从而产生一个全新的对象,原对象和新对象的引用类型字段互不影响。
在Java中,实现深拷贝的方式有多种,其中包括手动实现、使用序列化、使用第三方库等。一种常见的方式是通过对象的序列化和反序列化来实现深拷贝。
代码
/**
* 工具类,通过序列化和反序列化,创建了新的对象
*/
class DeepCopyUtil {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(object);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bis);
return (T) in.readObject();
}
}
class DeepCopyAddress implements Serializable {
private String city;
public DeepCopyAddress(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
class DeepCopyPerson implements Serializable {
private String name;
private DeepCopyAddress address;
public DeepCopyPerson(String name, DeepCopyAddress address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public DeepCopyAddress getAddress() {
return address;
}
public void setName(String name) {
this.name = name;
}
}
public class DeepCopyPrototypeExample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
DeepCopyAddress originalAddress = new DeepCopyAddress("广州");
DeepCopyPerson originalPerson = new DeepCopyPerson("John", originalAddress);
// 深拷贝
DeepCopyPerson clonedPerson = DeepCopyUtil.deepCopy(originalPerson);
// 修改拷贝对象的值
clonedPerson.setName("Jane");
clonedPerson.getAddress().setCity("深圳");
// 输出原来对象的值
System.out.println("Original Person Name: " + originalPerson.getName()); // Output: John
System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity()); // Output: 广州
}
}
原型模式其主要目的是通过复制现有对象来创建新的对象,而不是通过实例化类。通过克隆(或复制)一个现有对象,我们可以获得一个新对象,新对象与原对象具有相同的属性和状态。这样做的一个主要好处是避免了直接调用构造函数,从而提高了对象的创建效率。
结构图
代码
class Address implements Cloneable {
private String city;
public Address(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
private String name;
private Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public Address getAddress() {
return address;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 使用浅拷贝
Person clonedPerson = (Person) super.clone();
// 对引用类型字段进行拷贝
clonedPerson.address = (Address) address.clone();
return clonedPerson;
}
}
public class ShallowCopyPrototypeExample {
public static void main(String[] args) throws CloneNotSupportedException {
Address originalAddress = new Address("广州");
Person originalPerson = new Person("John", originalAddress);
// 使用浅拷贝创建新对象
Person clonedPerson = (Person) originalPerson.clone();
// 修改克隆对象的属性
clonedPerson.setName("Jane");
clonedPerson.getAddress().setCity("深圳");
// 输出原型对象和克隆对象的属性
System.out.println("Original Person Name: " + originalPerson.getName()); // Output: John
System.out.println("Original Person Address City: " + originalPerson.getAddress().getCity()); // Output: San Francisco
}
}
上面我们介绍了浅拷贝和深拷贝,这是我们用来实现原型模式的手段,然后当我们遇到下面几种场景时,可以考虑用原型模式