定義 原型模式:用原型實例指定創建對象的種類,並且通過複製這些原型創建新的對象。 從定義來看,我覺得最重要的一個詞就是 複製 ,所謂原型模式,你可以把它理解成對象的複製粘貼. 適用於比較複雜的對象,比如說你new一個對象,要傳十個參數(A a =new A(1,2,3,4,5,6,7,8,9,0))
定義
原型模式:用原型實例指定創建對象的種類,並且通過複製這些原型創建新的對象。
從定義來看,我覺得最重要的一個詞就是複製,所謂原型模式,你可以把它理解成對象的複製粘貼.
適用於比較複雜的對象,比如說你new一個對象,要傳十個參數(A a =new A(1,2,3,4,5,6,7,8,9,0)),那麼這種情況下,再建一個A的實例,是不是又得傳這麼多參數,如果A提供一個clone方法,複製一個A對象給你(
A A1 = a.clone());是不是方便多了呢?
接下來我們看看如何實現一個原型模式,原型模式需要原型類實現Cloneable介面,並且重寫clone方法:
public class Prototype implements Cloneable {
String desc = "啦啦啦啦";
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
}
在clone方法里.super.clone()調用的是父類Object的clone方法,我們看一下Object的源碼
protected native Object clone() throws CloneNotSupportedException;
這說明這個方法的實現不是java寫的,是用其他語言來實現的,是直接從記憶體中複製對象的
我們來做一個測試:
public static void main(String[] args) {
//新建一個對象實例,列印desc屬性值
Prototype prototype = new Prototype();
System.out.println(prototype.desc);
//複製一個對象實例,列印屬性值
Prototype prototype1 = prototype.clone();
System.out.println(prototype1.desc);
//比較這兩個對象是同一個對象嗎?
System.out.println(prototype==prototype1);
}
結果如下:
啦啦啦啦
啦啦啦啦
false
這說明瞭prototype1對象是prototype的一個副本,他們並不是同一個對象.
原型模式有兩種複製方式,一種是淺複製,一種是深複製,我們上面的例子中,其實是一種淺複製,那什麼是淺複製呢?
淺複製就是系統只會為我們自動複製對象的基本類型成員變數(八種基本類型int,long等)和String類型的成員變數.
那麼如果我們的類里有一個List類型的變數呢?那我們就需要重新改變一下我們的clone方法:
public class Prototype implements Cloneable,Serializable {
List list = new ArrayList();
String desc = "啦啦啦啦";
public Prototype clone() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Prototype) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
把對象寫道流里的過程是串列化(Serilization)過程;把對象從流中讀出來是並行化(Deserialization)過程. 寫在流里的是對象的一個拷貝,然後再從流里讀出來重建對象.這樣就複製了所有的變數.