原型模式
原型模式,指将一个对象作为原型,对其进行复制、克隆,产生一个和原对象属性相同的新对象。
普通模式复制对象
调用对象的 get/set 方法设置属性
public class Sheep {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Sheep sheep = new Sheep();
sheep.setName("Dolly");
sheep.setAge(1);
Sheep sheep2 = new Sheep();
sheep2.setName(sheep.getName());
sheep2.setAge(sheep.getAge());
// 各属性相同,但对象的地址不同
System.out.println("sheep:" + sheep);
System.out.println("sheep2:" + sheep2);
System.out.println("sheep:" + sheep.hashCode());
System.out.println("sheep2:" + sheep2.hashCode());
原型模式复制对象
public class Sheep implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return sheep;
}
}
Sheep sheep = new Sheep();
sheep.setName("Dolly");
sheep.setAge(1);
Sheep sheep2 = (Sheep) sheep.clone();
// 各属性相同,但对象的地址不同
System.out.println("sheep:" + sheep);
System.out.println("sheep2:" + sheep2);
System.out.println("sheep:" + sheep.hashCode());
System.out.println("sheep2:" + sheep2.hashCode());
浅拷贝
基本数据类型
当成员变量是基本数据类型,浅拷贝会直接进行值传递,将该属性值复制一份给新对象。
引用数据类型
当成员变量是引用数据类型,浅拷贝会进行引用传递,将该属性的引用地址复制一份给新对象。 此时,新对象和原型对象的成员变量指向同一个实例,在一个对象中修改这个成员变量,另一个对象也会受到影响。
浅拷贝使用默认的 clone() 方法实现。
public class Dog implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() {
Dog dog = null;
try {
dog = (Dog) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return dog;
}
}
public class Sheep implements Cloneable {
private String name;
private int age;
private Dog friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog getFriend() {
return friend;
}
public void setFriend(Dog friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
@Override
protected Object clone() {
Sheep sheep = null;
try {
sheep = (Sheep) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return sheep;
}
}
Dog friend = new Dog();
friend.setName("Tom");
friend.setAge(1);
Sheep sheep = new Sheep();
sheep.setName("Dolly");
sheep.setAge(2);
sheep.setFriend(friend);
Sheep sheep2 = (Sheep) sheep.clone();
// 属性值相同
System.out.println("sheep:" + sheep);
System.out.println("sheep2:" + sheep2);
// 对象的地址不同
System.out.println("sheep.hashCode:" + sheep.hashCode());
System.out.println("sheep2.hashCode:" + sheep2.hashCode());
// 引用数据类型成员变量的地址相同
System.out.println("sheep.friend:" + sheep.getFriend().hashCode());
System.out.println("sheep2.friend:" + sheep2.getFriend().hashCode());
深拷贝
不论成员变量是基本数据类型还是引用数据类型,深拷贝都会复制一份新的给新对象。
实现方式 1:重写 clone() 实现深拷贝
public class Dog implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() {
Dog dog = null;
try {
dog = (Dog) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return dog;
}
}
public class Sheep implements Cloneable {
private String name;
private int age;
private Dog friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog getFriend() {
return friend;
}
public void setFriend(Dog friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
@Override
protected Object clone() {
Sheep sheep = null;
try {
// 对基本数据类型的拷贝
sheep = (Sheep) super.clone();
// 对引用数据类型的拷贝;需要引用类型也实现 Cloneable 接口
sheep.friend = (Dog) friend.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return sheep;
}
}
Dog friend = new Dog();
friend.setName("Tom");
friend.setAge(1);
Sheep sheep = new Sheep();
sheep.setName("Dolly");
sheep.setAge(2);
sheep.setFriend(friend);
Sheep sheep2 = (Sheep) sheep.clone();
// 属性值相同
System.out.println("sheep:" + sheep);
System.out.println("sheep2:" + sheep2);
// 对象的地址不同
System.out.println("sheep.hashCode:" + sheep.hashCode());
System.out.println("sheep2.hashCode:" + sheep2.hashCode());
// 引用数据类型成员变量的地址也不相同
System.out.println("sheep.friend:" + sheep.getFriend().hashCode());
System.out.println("sheep2.friend:" + sheep2.getFriend().hashCode());
实现方式 2:通过对象序列化实现深拷贝
public class Dog implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// 所有相关对象都要实现 Serializable 接口,包括 Dog
public class Sheep implements Serializable {
private String name;
private int age;
private Dog friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Dog getFriend() {
return friend;
}
public void setFriend(Dog friend) {
this.friend = friend;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", friend=" + friend +
'}';
}
// 通过对象的序列化实现深拷贝
public Object deepClone() {
Sheep copySheep = null;
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
// 序列化
// 把当前对象输出到流
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 反序列化
// 从流中获取对象数据,并读取
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
copySheep = (Sheep) ois.readObject();
} catch (IOException | SecurityException | NullPointerException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (bos != null) {
bos.close();
}
if (oos != null) {
oos.close();
}
if (bis != null) {
bis.close();
}
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return copySheep;
}
}
Dog friend = new Dog();
friend.setName("Tom");
friend.setAge(1);
Sheep sheep = new Sheep();
sheep.setName("Dolly");
sheep.setAge(2);
sheep.setFriend(friend);
Sheep sheep2 = (Sheep) sheep.deepClone();
// 属性值相同
System.out.println("sheep:" + sheep);
System.out.println("sheep2:" + sheep2);
// 对象的地址不同
System.out.println("sheep.hashCode:" + sheep.hashCode());
System.out.println("sheep2.hashCode:" + sheep2.hashCode());
// 引用数据类型成员变量的地址也不相同
System.out.println("sheep.friend:" + sheep.getFriend().hashCode());
System.out.println("sheep2.friend:" + sheep2.getFriend().hashCode());