用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。
先上**:
定義乙個person類,實現cloneable介面,重寫clone()方法
public
class
person
implements
cloneable
@override
protected person clone()
catch
(clonenotsupportedexception e)
return p;
}@override
public string tostring()
';}}
客戶端呼叫:
public
class
client
system.out.
println
("p2:"
+p2.
tostring()
);//p2:person
}}
輸出與預想一致,拷貝成功!
再person類中再加乙個引用型別的成員變數location,**如下:
person跟location類:
public
class
person
implements
cloneable
public
void
setlocation
(location location)
public
person
(string name,
int age, location location)
@override
protected person clone()
catch
(clonenotsupportedexception e)
return p;
}@override
public string tostring()
';}}
class
location
@override
public string tostring()
';}}
客戶端:
public
class
client
}輸出:
false
p1:person
},location hashcode:
460141958
p2:person
},location hashcode:
460141958
可以看出,location的hashcode值相等,說明是同乙個物件,其實想想也對,person複製物件的時候會把location屬性也複製,但是複製的肯定是引用,複製的引用指向了原來的location物件。
對於資料型別是基本資料(包括string)型別的成員變數,淺拷貝會直接進行值傳遞,也就是將該屬性值複製乙份給新的物件。
對於資料型別是引用資料型別的成員變數,比如說成員變數是某個陣列、某個類的物件等,那麼淺拷貝會進行引用傳遞,也就是只是將該成員變數的引用值(記憶體位址)複製乙份給新的物件。因為實際上兩個物件的該成員變數都指向同乙個例項。在這種情況下,在乙個物件中修改該成員變數會影響到另乙個物件的該成員變數值
想要使得上述的location物件也拷貝乙份,然後person物件的成員變數指向新的location物件,就需要深拷貝。
方法也很簡單,讓location也實現cloneable介面,重新clone()方法,在person clone() 中呼叫location的clone() 即可,其實就是把每個物件都clone() 了一遍。
**如下:
person和location類:
public
class
person
implements
cloneable
public
void
setlocation
(location location)
public
person
(string name,
int age, location location)
@override
protected person clone()
catch
(clonenotsupportedexception e)
return p;
}@override
public string tostring()
';}}
class
location
implements
cloneable
@override
protected object clone()
throws clonenotsupportedexception
@override
public string tostring()
';}}
client:
public
class
client
}輸出:
false
p1:person
},location hashcode:
460141958
p2:person
},location hashcode:
1163157884
深拷貝成功,但是如果person物件特別複雜,其中有很多引用型別的成員變數,那就很麻煩。
還有一種深拷貝,序列化。
**:persion和location類:
public
class
person
implements
serializable
public
void
setlocation
(location location)
public
person
(string name,
int age, location location)
public person deepclone()
catch
(exception e)
finally
catch
(exception e2)}}
@override
public string tostring()
';}}
class
location
implements
serializable
@override
public string tostring()
';}}
client:
public
class
client
}輸出:
false
p1:person
},location hashcode:
325040804
p2:person
},location hashcode:
1595428806
建立新的物件比較複雜時,可以利用原型模式簡化物件的建立過程,同時也能夠提高效率,簡單的物件new的效率比clone高。
不用重新初始化物件,而是動態地獲得物件執行時的狀態
如果原始物件發生變化(增加或者減少屬性),其它轉殖物件的也會發生相應的變化,無需修改**
在實現深轉殖的時候可能需要比較複雜的**
缺點:需要為每乙個類配備乙個轉殖方法,這對全新的類來說不是很難,但對已有的類進行改造時,需要修改其源**,違背了 ocp 原則,這點請同學們注意.
設計模式 原型模式
1.首先分析原型模式的由來 一般來說,建立乙個物件可以由以下方法 知道物件的具體型別,直接用new生成。不知道型號,知道相應的需求,可以使用工廠方法模式。根據乙個已有的物件來複製為乙個新的物件,可以使用原型模式。2.原型模式可以簡單理解為拷貝原型物件得到新的物件。想象乙個配鑰匙的小店,給店主乙個原有...
設計模式 原型模式
魔術師手拿一張百元大鈔,瞬間又變出兩張。也像配鑰匙一樣,拿一把鑰匙,老師傅就能做出另乙個一模一樣的。像這種複製我們並不陌生,類似於我們設計中的原型模式 本文將從以下幾點 原型模式 概述 結構圖 淺複製深複製 總結 用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。允許乙個物件再建立另外...
設計模式 原型模式
原型模式 用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。1 假設我們現有乙個物件,但是它的型別需要執行期確定,我們不知道它的動態型別是什麼,現在我們想建立它的副本。顯然通過建構函式建立是很麻煩的,這時候我們可以使用原型模式中的clone函式直接得到該物件的副本。2 有些時候我們想要...