1 介绍
Prototype模式是一种对象创建型模式,采取复制原型对象的方法来创建对象的实例。创建的目标对象拥有和原型对象同样的结构和数据,并且是两个独立的对象。
- 实现复制的方式:
- 引用方式
- 克隆方式
2 引用方式
先上代码
Person.class
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
MainClass.class
public class MainClass {
public static void main(String[] args) {
<!--实例化一个person对象,并赋值--!>
Person person1 = new Person();
person1.setName("哈哈");
person1.setAge(11);
<!--引用赋值--!>
Person person2 = person1;
<!--修改person1的数据--!>
person1.setAge(12);
System.out.println("person1.age:"+person1.getAge());
System.out.println("person2.age:"+person2.getAge());
}
看到运行结果后,我们就会发现,当我们使用引用方式赋值后,虽然我们只是修改了原型对象(person1)的数据,但是目标对象(person2)的数据也会随着一起被修改。因为使用引用方式赋值,两个对象虽然有相同的结构,但是都引用着同一份数据。
当我们的需求希望再修改目标对象时,原型对象不会被修改。那么我们就需要使用<a>克隆</a>来实现复制
3 克隆方式
相对于引用方式,克隆方式不仅可以复制原型对象的结构和数据,还可以做到对单方数据进行修改不会影响到另一方。即使用克隆方式复制对象时,会在堆中分配新的地址存放复制的目标对象。
3.1 浅度克隆
当对象中有复杂类型(List、Set等)时,浅度克隆将复制不了对象中的复杂属性,只能克隆普通属性。
就像这两只小小猪一样,虽然是克隆猪,但是做不到完全一样。
浅度克隆的实现方式
Person.class
//要使用克隆必须要实现Cloneable接口,该接口只是声明该类可被克隆,并没有代码
public class Person implements Cloneable{
private String name;
private Integer age;
private Set<String> friends = new HashSet<>();
public Person getPerson(){
try {
return (Person) super.clone();
// 当没有实现Cloneable时clone会报异常
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Set<String> getFriends() {
return friends;
}
public void setFriends(Set<String> friends) {
this.friends = friends;
}
}
MainClass.class
public class MainClass {
public static void main(String[] args) {
Person person1 = new Person();
person1.setName("哈哈");
person1.setAge(11);
Set<String> friends = new HashSet<>();
friends.add("jon");
friends.add("daa");
person1.setFriends(friends);
// 使用克隆方式复制对象
Person person2 = person1.getPerson();
System.out.println("*****************普通类型*******************");
person1.setAge(12);
System.out.println("person1.age:"+person1.getAge());
System.out.println("person2.age:"+person2.getAge());
System.out.println("*****************复杂类型*******************");
friends.add("new");
person1.setFriends(friends);
System.out.println("person1.age:"+person1.getFriends().toString());
System.out.println("person2.age:"+person2.getFriends().toString());
}
}
我们可以看到,普通类型的数据会被克隆下来,但是复杂类型的属性还是使用的是引用方式复制。为了解决这一问题呢,深度克隆模式就出来了。
3.2 深度克隆
使用深度克隆可以真正的实现对象的完全克隆,不管时简单类型还是复杂类型,但是相对的代码的灵活性不够高。
实现方式
Person.class
//要使用克隆必须要实现Cloneable接口,该接口只是声明该类可被克隆,并没有代码
public class Person implements Cloneable{
private String name;
private Integer age;
private Set<String> friends = new HashSet<>();
public Person getPerson(){
try {
Person person1 = (Person) this.clone();
<!--先克隆,再将原型对象中的复杂类型数据取出放入目标对象中返回--!>
Set<String> friends1 = new HashSet<>();
for(String friend : this.getFriends()){
friends1.add(friend);
}
person1.setFriends(friends1);
return person1;
// 当没有实现Cloneable时clone会报异常
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Set<String> getFriends() {
return friends;
}
public void setFriends(Set<String> friends) {
this.friends = friends;
}
}
MainClass.class不变
最近刚学设计模式,哪理解错了,望各位湿兄大佬多多指正