一,什麼是原型模式。
Prototype 模式 是一種對象創建型模式,它採取複製原型對象的方法來創建對象的實例。使用Prototype模式創建的實例,具有與原型一樣的數據。
二,原型模式的特點。
由原型對象自身創建目標對象,通過實現接口 (Cloneable) ,目標對象是原型對象的一個克隆,不僅僅是具有相同的結構,屬性,還與原型對象具有相同的值。
但是 在實例化目標對象,和實例化原型對象後, 在jvm 虛擬機 堆內存裏是 兩個地址不相同的引用對象。
根據對象克隆深度層次的不同,有淺度克隆與深度克隆。
三,實例。
3.1 淺度克隆
public class ProtoType implements Cloneable{
//淺度克隆基礎數據類型
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public ProtoType cloneObject(){
try {
//每一個對象的父類的都是Object, object 實現了clone(), 這裏可以直接調用
return (ProtoType)super.clone();
} catch (CloneNotSupportedException e) {
//沒有實現(Cloneable)接口,會拋出不支持克隆異常,
e.printStackTrace();
return null;
}
}
@Override
public String toString() {
return "ProtoType{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", peopleList=" + peopleList +
'}';
}
}
public class Test {
public static void main(String[] args) {
//具有相同的值,和結構 ,淺度克隆
ProtoType protoType = new ProtoType();
protoType.setName("張三");
protoType.setAge("18");
System.out.println("原型對象===" +protoType.toString());
ProtoType protoType2 = protoType.cloneObject();
System.out.println("克隆對象===" +protoType.toString());
System.out.println("原型對象=克隆對象:"+(protoType == protoType2));
}
}
3.2 深度克隆對象
public class ProtoType implements Cloneable{
private String name;
private String age;
/**
* 深度克隆引用類型,使原型對象中的引用數據類型 與 模型對象中的引用數據類型 地址不一致
*/
private List<String> peopleList;
public List<String> getPeopleList() {
return peopleList;
}
public void setPeopleList(List<String> peopleList) {
this.peopleList = peopleList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public ProtoType cloneObject(){
try {
//每一個類的父類的都是Object, object 實現了clone(), 這裏可以直接調用
ProtoType protoType =(ProtoType)super.clone();
//深度克隆原型對象中的引用數據類型,其實就是創建一個新的對象,
// 使原型對象中的引用數據類型 被克隆 模型對象時,讓引用數據類型 地址不一致
List<String> list = new ArrayList<String>();
for(String str:this.peopleList){
list.add(str);
}
protoType.setPeopleList(list);
return protoType;
} catch (CloneNotSupportedException e) {
//沒有實現(Cloneable)接口,會拋出不支持克隆異常,
e.printStackTrace();
return null;
}
}
@Override
public String toString() {
return "ProtoType{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", peopleList=" + peopleList +
'}';
}
}
public class Test {
public static void main(String[] args) {
//深度克隆
ProtoType protoType1 = new ProtoType();
List<String> peopleList = new ArrayList<String>();
peopleList.add("小王");
peopleList.add("小李");
protoType1.setPeopleList(peopleList);
ProtoType protoType2 = protoType1.cloneObject();
System.out.println(protoType1.getPeopleList());
System.out.println(protoType2.getPeopleList());
peopleList.add("小美");
protoType1.setPeopleList(peopleList);
System.out.println(protoType1.getPeopleList());
System.out.println(protoType2.getPeopleList());
}
}
總結:
在創建對象的時候,我們不只是希望被創建的對象繼承其基類的基本結構,還希望繼承原型對象的數據
希望對目標對象的修改不影響既有的原型對象(深度克隆的時候可以完全互補影響)
隱藏克隆操作的細節,很多時候,對對象本身的克隆需要涉及到本身的數據細節