【图解设计模式系列】The Prototype Pattern: 原型模式
定义:
原型模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的数据。
原型模式的三个特点:
1.由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。
2.目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。
3.根据对象克隆深度层次的不同,有浅克隆与深克隆。
原型模式的三个应用场景
-
在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据。
-
希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)。
-
隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。
![在这里插入图片描述]()
实例
Person类实现了Clonable接口,该接口和Serializable一样,仅仅是一个标志,表明该类可以被克隆。同时它提供了一个clone方法,需要注意的是clone方法是Object中的方法,Person进行了重写。
public class Person implements Cloneable{
private String name;
private int age;
private String sex; public Person clone() {
try {
Person person = (Person)super.clone(); return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
//省略了setter和getter
}
public class MainClass {
public static void main(String[] args) {
//Person1
Person person1 = new Person();
person1.setName("lifengxing");//name
person1.setAge(30);//age
person1.setSex("男");//sex
List<String> friends = new ArrayList<String>();
friends.add("James");
friends.add("Yao");
person1.setFriends(friends);//friends
//0.克隆Person1得到person2
Person person2 = person1.clone();
//1.验证person1和person2的所有属性值
System.out.println(person2.getName());//lifengxing
System.out.println(person2.getAge());//30
System.out.println(person2.getSex());//男
System.out.println(person2.getFriends());//[James, Yao]
//2.验证基本属性
//person1变性
person1.setSex("女");
System.out.println("person1变性为"+person1.getSex());//性别变为女
System.out.println("person2依旧为"+person2.getSex());//性别仍为男
//3.验证引用属性
//person1多了一个朋友kitty
List<String> li = person1.getFriends();
li.add("kitty");
person1.setFriends(li);
System.out.println("person1现在的朋友:"+person1.getFriends());//[James, Yao, kitty]
System.out.println("person2现在的朋友:"+person2.getFriends());//[James, Yao, kitty]
}
0处调用clone方法生成了新的对象,1处通过打印结果可知克隆后的对象与原对象属性值完全一样。
但是仅仅通过打印结果相同并不能说明person2就一定是引用了一个新创建的对象,难道就不可能是person2指向了person1吗,也就是Person person2=person1;
于是,2处进行验证:
将person1进行变性,打印结果显示虽然person1确实变性成功,但是person2根本不受影响。这也就说明clone操作一定是创建了新的对象。
3处进一步验证:person1由于变性后魅力大增,结识了新的朋友kitty,打印结果发现person2也多了一个kitty朋友。为什么跟上面的不一致了呢?
这里涉及了深克隆和浅克隆的知识。
要想对person1进行深克隆,只需要在clone方法中手动对引用(复杂)类型的属性手动克隆一下就行了。
public class Person implements Cloneable{
private String name;
private int age;
private String sex;
private List<String> friends;
public Person clone() {
try {
Person person = (Person)super.clone();
//a.手动对引用类型的属性friends进行克隆
List<String> clonefriends = new ArrayList<String>();
clonefriends.addAll(this.getFriends());
person.setFriends(clonefriends);
return person;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
return null;
}
}
}
再次运行程序,结果就是person2完全不受person1影响了,也就是person2对person1进行了深克隆。


浙公网安备 33010602011771号