1、原型模式
原型模式是指將一個對象作爲原型,對其進行復制、克隆,產生一個和原對象類似的對象。原型模式是一種創建型模式。
原型模式的工作原理很簡單:將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝自己來實現創建過程。原型模式是一種“另類”的創建型模式,創建克隆對象的工廠就是原型類自身,工廠方法由克隆方法來實現。
組成:
1) Prototype(抽象原型類):它是聲明克隆方法的接口,是所有具體原型類的公共父類,可以是抽象類也可以是接口,甚至還可以是具體實現類。
2)ConcretePrototype(具體原型類):它實現在抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象。
類圖:
通用的克隆方法是在具體原型實現類中實例化(克隆)一個與自身類型相同的對象並將其返回;
代碼:
abstract class Prototype{
public Prototype clone(){
return null;
}
}
class ConcretePrototype extends Prototype{
private String sttr ;
public String getSttr() {
return sttr;
}
public void setSttr(String sttr) {
this.sttr = sttr;
}
public Prototype clone(){
ConcretePrototype prototyoe = new ConcretePrototype();
prototyoe.setSttr(this.sttr);
return prototyoe;
}
}
適用場景:創建對象成本較大,如初始化佔用較長時間、佔用大量cpu資源等,新的對象可以通過原型對象複製產生新的對象。
總結 :使用原型模式在創建新的較複雜對象時,使用原型可以簡化對象創建過程,通過複製提高效率。但是每一個類配備一個克隆方法,而且該克隆方法位於一個類的內部,當對已有的類進行改造時,需要修改源代碼,違背了“開閉原則”。
2、JDK中原型模式應用
在jdk中,Prototype原型抽象類對應Cloneable接口,一個原型類,只需要實現 Cloneable 接口,覆寫 clone 方法,此處 clone 方法可以改成任意的
名稱,因爲 Cloneable 接口是個空接口,你可以任意定義實現類的方法名,如 cloneA 或者 cloneB,因 爲此處的重點是 super.clone()這句話, super.clone()調用的是
Object 的 clone()方法,而在 Object 類中。
淺複製:將一個對象複製後,基本數據類型的變量都會重新創建,而引用類型,指向的還是原對象所指 向的。
深複製:將一個對象複製後,不論是基本數據類型還有引用類型,都是重新創建的。簡單來說,就是深 複製進行了完全徹底的複製,而淺複製不徹底。
淺複製實例:
class ShallowClone implements Cloneable{
String name = "xl" ;
int age = 20 ;
@Override
protected ShallowClone clone() {
// TODO Auto-generated method stub
Object object = null ;
try{
object = super.clone();
return (ShallowClone)object;
}catch(CloneNotSupportedException EX){
System.out.println("NOT SUPPORT CLONE !!");
return null ;
}
}
}
深複製實例:
class DeepClone implements Cloneable{
String name = "xl" ;
int age = 20 ;
protected DeepClone deepClone() throws CloneNotSupportedException,IOException, ClassNotFoundException{
/* 寫入當前對象的二進制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 讀出二進制流產生的新對象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepClone)ois.readObject();
}
}