一、什么是原型模式
Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。
二、原型模式的特点
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进行了深克隆。