目录
一.什么是原型模式
原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。(拿一个原对象,去复制一个新对象);
调用者不需要知道任何创建细节,不调用构造函数
属于创建型模式
优点:
- 当对象的赋值过程比较繁琐时使用原型模式非常的方便
缺点:
- 必须配备克隆((或者可拷贝)方法
- 对克隆复杂对象或对克隆出的对象进行复杂改造时,易带来风险。
- 深拷贝、浅拷贝要运用得当
原型模式的适用场景:
- 类初始化消耗资源较多。
- new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
- 构造函数比较复杂。
- 循环体中生产大量对象时。
二.浅克隆
浅克隆就是克隆的对象与原对象的引用类型的引用地址还相同
PrototypeA
public class PrototypeA implements Cloneable{
private String name;
private int age;
private List<String> hobbies;
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 List<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
@Override
public PrototypeA clone() throws CloneNotSupportedException {
// PrototypeA prototype = new PrototypeA();
// prototype.setAge(this.age);
// prototype.setName(this.name);
// prototype.setHobbies(this.hobbies);
//Object.clone就是浅克隆
return (PrototypeA) super.clone();
}
}
Test:
public class Test1 {
public static void main(String[] args) {
PrototypeA prototype = new PrototypeA();
prototype.setName("ws");
prototype.setAge(18);
List<String> hobbies = new ArrayList<>();
hobbies.add("唱");
hobbies.add("跳");
prototype.setHobbies(hobbies);
System.out.println("原对象引用类型对象的值" + prototype.getHobbies());
//浅克隆对象
PrototypeA clone = prototype.clone();
System.out.println("cole对象引用类型对象的值" + clone.getHobbies());
System.out.println(prototype.getHobbies() == clone.getHobbies());
}
}
这说明了克隆对象与原对象的引用类型对象的引用地址相同,也就是改变其中一个对象中的值另一个也会跟着改变
三.序列化深克隆
相当于把对象序列到内存中,然后在把内存中的序列化对象再反序列化得到新的对象
public IPrototype deepClone() {
PrototypeA prototype = null;
try {
//把对象先序列化内存中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
prototype = (PrototypeA) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return prototype;
}
Test
public class Test1 {
public static void main(String[] args) {
PrototypeA prototype = new PrototypeA();
prototype.setName("ws");
prototype.setAge(18);
List<String> hobbies = new ArrayList<>();
hobbies.add("唱");
hobbies.add("跳");
prototype.setHobbies(hobbies);
System.out.println("原对象引用类型对象的值" + prototype.getHobbies());
// //浅克隆对象
// PrototypeA clone = prototype.clone();
//序列化深克隆
PrototypeA clone = prototype.deepClone();
System.out.println("cole对象引用类型对象的值" + clone.getHobbies());
System.out.println(prototype.getHobbies() == clone.getHobbies());
//TODO 关闭流
}
}
四.递归深克隆
递归深克隆就是把浅克隆后的引用类型再克隆一遍
public PrototypeA recursionDeepClone() throws CloneNotSupportedException {
PrototypeA prototype = (PrototypeA) super.clone();
//因为浅克隆克隆后的引用类型地址相同
//所以我们可以递归克隆,引用类型再克隆一遍
prototype.hobbies = (List)((ArrayList)prototype.hobbies).clone();
return prototype;
}
Test:
public class Test1 implements Cloneable{
public static void main(String[] args) {
PrototypeA prototype = new PrototypeA();
prototype.setName("ws");
prototype.setAge(18);
List<String> hobbies = new ArrayList<>();
hobbies.add("唱");
hobbies.add("跳");
prototype.setHobbies(hobbies);
System.out.println("原对象引用类型对象的值" + prototype.getHobbies());
// //浅克隆对象
// PrototypeA clone = prototype.clone();
//序列化深克隆
// PrototypeA clone = prototype.deepClone();
//递归深克隆
PrototypeA clone = prototype.recursionDeepClone();
System.out.println("cole对象引用类型对象的值" + clone.getHobbies());
System.out.println(prototype.getHobbies() == clone.getHobbies());
}
}
浅克隆就是引用地址还相同, 深克隆就是引用地址不同