第五章:原型模式
一、问题引入
有一个 Sheep 对象,现要求克隆两份一模一样的对象
常规做法:
Sheep 对象
@Data
@ToString
@AllArgsConstructor
public class Sheep implements Cloneable{
private int id;
private String name;
private int age;
private boolean male;
}
使用 new 来克隆对象
public static void main(String[] args) {
Sheep duoli = new Sheep(1, "多利", 3, true);
Sheep xiaoen = new Sheep(duoli.getId(), duoli.getName(), duoli.getAge(), duoli.isMale());
Sheep meiyy = new Sheep(duoli.getId(), duoli.getName(), duoli.getAge(), duoli.isMale());
}
我们发现使用 new 来克隆一个对象实在是有些麻烦,假入某个对象有几十个甚至更多属性,那么我们传参都要写半天。
二、原型模式
所以如果这个对象自带一个 clone 的方法就好了,巧了,因为所有对象都继承自 Object,而 Object 内部就有一个 clone 方法,不过这个方法是不能直接使用的。
@Data
@ToString
@AllArgsConstructor
public class Sheep implements Cloneable{
private int id;
private String name;
private int age;
private boolean male;
@Override
public Sheep clone() throws CloneNotSupportedException {
return (Sheep) super.clone();
}
}
测试 clone 方法
public static void main(String[] args) throws CloneNotSupportedException {
Sheep duoli = new Sheep(1, "多利", 3, true);
Sheep xiyy = duoli.clone();
Sheep lanyy = duoli.clone();
System.out.println(xiyy);
System.out.println(lanyy);
}
原型模式定义:
- 用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象
上面我们通过原型对象自己的 clone 方法拷贝对象的方式就是原型模式
三、浅拷贝
问:什么是浅拷贝?
答:调用原型的拷贝方法后产生的克隆对象的一些字段会随着原型的改变而变化,就是浅拷贝
问:浅拷贝的实现?
答:
? 1)数据类型是基本数据类型的成员变量,浅拷贝直接进行值传递
? 2)数据类型是引用数据类型的成员变量,浅拷贝进行的是引用传递,所以说原型的改变可能造成拷贝对象的改变
上面我们使用 Object 对象的 clone 方法拷贝就属于浅拷贝
四、深拷贝
1. 深拷贝概念
问:什么是深拷贝?
答:简单的定义就是不管原型对象如何改变都不会对拷贝对象造成任何影响
问:怎么实现深拷贝?
答:
? 1)原型的成员变量如果是基本数据类型或者是引用的是一个不可变对象的引用数据类型,那么和浅拷贝一样的操作就行
? 2)成员变量是如果是一个引用可变对象的引用类型,那么就需要对引用的对象也进行深拷贝
2. 深拷贝实现
方法一:重写 clone 方法
Person 类
@Data
@ToString
@AllArgsConstructor
public class Person implements Cloneable{
private String name;
private int age;
private boolean male;
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
Sheep 类
@Data
@ToString
public class Sheep implements Cloneable{
private int id;
private String name;
private int age;
private boolean male;
private Person master;
public Sheep(int id, String name, int age, boolean male) {
this.id = id;
this.name = name;
this.age = age;
this.male = male;
}
@Override
public Sheep clone() throws CloneNotSupportedException {
Sheep shadow = (Sheep) super.clone();
shadow.master = master == null ? null : master.clone();
return shadow;
}
}
方式二:序列化的方式(推荐)
Person 类
@Data
@ToString
@AllArgsConstructor
public class Person implements Cloneable, Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private boolean male;
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
Sheep 类
@Data
@ToString
public class Sheep implements Cloneable, Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private int age;
private boolean male;
private Person master;
public Sheep(int id, String name, int age, boolean male) {
this.id = id;
this.name = name;
this.age = age;
this.male = male;
}
@Override
public Sheep clone() throws CloneNotSupportedException {
Sheep shadow = 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);
shadow = (Sheep) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return shadow;
}
}
|