關(guān)于克隆,我們會想到《西游記》里面孫悟空的猴毛分身,也會想到《火影忍者》里面的影分身之術(shù)。他們都是用一個物體復(fù)制若干個一模一樣的物體。在面向?qū)ο蟮南到y(tǒng)中,我們也可以通過克隆來復(fù)制一些對象---也就是我們所說的原型模式
用原型實例指定創(chuàng)建對象的種類,通過拷貝這些原型創(chuàng)建新的對象,也就是利用一個原型對象來指明我們要創(chuàng)建對象的類型,然后通過復(fù)制這個對象來獲取一模一樣的對象實例
一個簡單的原型模式Demo
public class PrototypeClass implements Cloneable{
@Override
protected PrototypeClass clone(){
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass)super.clone();
}catch (CloneNotSupportedException e){
}
return prototypeClass;
}
}
- 實現(xiàn)Cloneable接口,在JVM中只有具有這個標(biāo)記的對象才有可能被拷貝
- 重寫覆蓋Clone()方法
為什么要用原型模式
- 性能優(yōu)良。 原型模式是在內(nèi)存二進(jìn)制流的拷貝,比直接new一個對象性能要好得多。所以特別是要在一個循環(huán)體內(nèi)產(chǎn)生大量對象的時候,原型模式更好體現(xiàn)其優(yōu)點
- 避開構(gòu)造函數(shù)的束縛(既是優(yōu)點也是缺點)
直接在內(nèi)存中拷貝,構(gòu)造函數(shù)是不會執(zhí)行的
原型模式應(yīng)用場景
- 資源優(yōu)化場景
- 性能和安全要求場景
- 一個對象多個修改者的場景
兩種拷貝方式
淺拷貝
只拷貝本對象,對象內(nèi)部的數(shù)組、引用對象都不拷貝,還是指向原生對象的內(nèi)部元素地址。原始類型(int、long、char)以及String都會被拷貝
如何才能保證成員變量不被拷貝(保證以下兩個條件)
- 必須是類的成員變量,而不是方法內(nèi)變量
- 必須是一個可變的引用對象,而不是一個原始類型或者不可變對象
public class Thing implements Cloneable {
private List<String> list = new ArrayList<String>();
@Override
protected Thing clone(){
Thing thing = null;
try {
thing = (Thing)super.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return thing;
}
public void setValue(String value){
this.list.add(value);
}
public List<String> getValue(){
return this.list;
}
}
淺克隆是不安全的方式,兩個對象共享了一個私有變量,大家都能夠進(jìn)行修改。
深拷貝
public class DeepThing implements Cloneable {
private ArrayList<String> list = new ArrayList<String>();
@Override
protected DeepThing clone(){
DeepThing thing = null;
try {
thing = (DeepThing)super.clone();
this.list = (ArrayList<String>)this.list.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return thing;
}
public void setValue(String value){
this.list.add(value);
}
public List<String> getValue(){
return this.list;
}
}
總結(jié)
- 原型模式向客戶隱藏了創(chuàng)建對象的復(fù)雜性,客戶只需要知道創(chuàng)建對象類型,就可以獲得對象一模一樣的新對象。
- 有兩種克隆方式:深克隆、淺克隆
- 淺克??;不安全,對象公有私有變量
- 有時對象的復(fù)制可能會比較復(fù)雜