原型模式,我的理解就是copy原型的数据,与=号赋值不同,前者的地址是不一致的,仅仅是使用了原型的数据。如A为原型,B为原型克隆而来,原型模式下A和B仅数据相同,所以A,B间在浅深度下改变基本类型数据时是不影响的,在重深度下改变引用类型下数据也是要不影响的。
浅深度下:
package singleton;
import java.util.List;
public class User implements Cloneable{
private String name;
private int age;
private List<String> list;
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
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 User getClone() {
try {
return (User) this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
package singleton;
public class MainClass {
public static void main(String[] args) {
User user = new User();
user.setName("zhangsan");
user.setAge(10);
User user2 = user.getClone();
System.out.println(user.getName());
System.out.println(user2.getName());
user.setName("lissi");
System.out.println(user.getName());
System.out.println(user2.getName());
}
}
输出结果
zhangsan
zhangsan
lissi
zhangsan
原型中基本类型值的改变了,从输出结果可以看出user1中的值并没有变,故两者地址不一致。在轻深度下,如果原型中引用类型的值改变,则user1中对应的属性值也是改变的。如:
package singleton;
import java.util.ArrayList;
public class MainClass {
public static void main(String[] args) {
User user = new User();
user.setName("zhangsan");
user.setAge(10);
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
user.setList(list);
User user2 = user.getClone();
System.out.println(user.getList());
System.out.println(user2.getList());
list.add("three");
System.out.println(user.getList());
System.out.println(user2.getList());
}
}
输出结果是:
[one, two]
[one, two]
[one, two, three]
[one, two, three]
可以看出是两者是一同改变的,所以当需要重深度地克隆话,则需更改User中的getClone方法
public User getClone() {
try {
User clone =(User) this.clone();
ArrayList<String> arrayList = new ArrayList<String>();
this.getList().forEach((e)->arrayList.add(e));
clone.setList(arrayList);
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
输出结果为:
[one, two]
[one, two]
[one, two, three]
[one, two]
其它引用类型相同处理,也可以使用spring的BeanUtils来转换引用类型。使用场景:
- 在创建对象的时候,我们不只是希望被创建的对象继承
其基类的基本结构,还希望继承原型对象的数据。
- 希望对目标对象的修改不影响既有的原型对象(深度克
隆的时候可以完全互不影响)。
- 隐藏克隆操作的细节。很多时候,对对象本身的克隆需
要涉及到类本身的数据细节。