原型模型應該屬於容易理解簡單設計模型了,若是咱們有個對象A,須要大量能夠對它進行拷貝,或者須要在一個循環體內建立對象,假如對象建立過程比較複雜或者循環次數不少的話,使用原型模式能夠簡化建立過程,並且可使系統的總體性能提升不少。克隆的對象可能包含一些已經修改過的屬性,保留着你想克隆對象的值,而new出來的對象的屬性全是一個新的對象,對應的屬性沒有值,因此咱們還要從新給這個對象賦值。即當須要一個新的對象來保存當前對象的「狀態」就靠clone方法了。那麼我把這個對象的臨時屬性一個一個的賦值給我新new的對象不也行嘛?能夠是能夠,可是一來麻煩不說,二來,你們經過源碼發現clone是一個native方法,快,在底層實現的。數組
使用原型模式複製對象不會調用類的構造方法,而是經過cloneable接口的clone方法來完成的,它直接在內存中複製數據,所以不會調用到類的構造方法。不但構造方法中的代碼不會執行,甚至訪問權限都對原型模式無效。ide
克隆時候咱們須要注意,咱們有區分淺克隆和深克隆。性能
淺克隆是指拷貝對象時僅僅拷貝對象自己(包括對象中的基本變量),而不拷貝對象包含的引用指向的對象。測試
深克隆不只拷貝對象自己,並且拷貝對象包含的引用指向的全部對象。 this
object類的clone方法只會拷貝對象中的基本的數據類型,對於數組、容器對象、引用對象等都不會拷貝,這就是淺拷貝。若是要實現深度拷貝,必須將原型中的數據、容器對象、引用對象等另行拷貝。spa
具體不一樣地方以下圖所示:.net
簡單來講,淺度克隆就是隻是實現了cloneable接口,默認的是實現了super的方法,默認的是使用object的克隆方法,它只能對基本類型進行一個複製,而對於指向對象的引用不能作複製,值是把克隆的引用都指向了是原來對象同一塊內存(假複製),這個同一塊內存的任何參數發生了變化,相關引用也取值必然也是發生變化。設計
深度克隆實際上是須要咱們覆蓋重寫cloneable接口,咱們對若是默認裏面還含有對象的引用,再進行一個複製,這樣才能達到給複製對象裏面引用對象開闢一個新的內存,才能達到真正的徹底複製。對象
下面咱們看個例子:blog
//建立一個老師對象,每一個學生都有一個老師,咱們這兒只是用來測試cloneable接口的問題
public class Teacher implements Cloneable{
public String name;
public Teacher(){
name = "init teacher";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class Student implements Cloneable {
private int age;
private String name;
private Teacher teacher = new Teacher();
public Teacher getTeacher() {
return teacher;
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
//深度克隆
// Student s = (Student) super.clone();
// s.teacher = (Teacher) s.teacher.clone();
// return s;
//淺度克隆
return super.clone();
}
/**
* @param args
* @throws CloneNotSupportedException
*/
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student(20, "張三");
// Teacher teacher = new Teacher();
// student1.setTeacher(teacher);
student1.teacher.name = "李老師";
Student student2 = (Student) student1.clone();
student2.teacher.name = "張老師";
student2.setAge(22);// 注意修改student2的age值 可是沒有影響 student1的值
System.out.println("student1:" + student1.getName() + "-->"+ student1.getAge() + " --->" + student1.teacher.name);
System.out.println("student2:" + student2.getName() + "-->"+ student2.getAge()+ " --->" + student2.teacher.name);
}
}
咱們看看淺克隆打印結果:
student1:張三-->20 --->張老師
student2:張三-->22 --->張老師
深克隆打印結果:
student1:張三-->20 --->李老師
student2:張三-->22 --->張老師
以上內容有部分參考
https://blog.csdn.net/lovezhaohaimig/article/details/80372233