???名稱:Prototype(原型模式)
?
?? 意圖:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。
?
?? 適用環(huán)境:當(dāng)一個(gè)系統(tǒng)應(yīng)該獨(dú)立于它的產(chǎn)品創(chuàng)建、構(gòu)成和表示時(shí),要使用Prototype模式;以及要實(shí)例化的類是在運(yùn)行時(shí)刻指定時(shí),例如,通過(guò)動(dòng)態(tài)裝載;或者為了避免創(chuàng)建一個(gè)與產(chǎn)品類層次平行的工廠類層次時(shí);或者 當(dāng)一個(gè)類的實(shí)例只能有幾個(gè)不同狀態(tài)組合中的一種時(shí)。建立相應(yīng)數(shù)目的原型并克隆它們可能比每次用合適的狀態(tài)手工實(shí)例化該類更方便一些。

????結(jié)構(gòu)圖:如下

?Prototype.gif

java中提供了clone()來(lái)實(shí)現(xiàn)對(duì)象克隆。所以prototype模式變得了很簡(jiǎn)單。

只要實(shí)現(xiàn)接口Cloneable就可以了

package?prototype;
import?java.util.Date;
import?java.io.*;
public?class?Monkey?implements?Cloneable{
????
private?int?height;
????
private?int?weight;
????
private?GoldRingedStaff?staff;
????
private?Date?birthDate;
????
????
public?Monkey(){
????????birthDate
=new?Date();
????????staff
=new?GoldRingedStaff();
????}
?
???? ????
//淺拷貝
???????
??public?Object?clone(){
????????Monkey?temp
=null;
????????
try{
????????????temp
=(Monkey)super.clone();
????????}
catch(CloneNotSupportedException?e){
????????}
finally{
????????????
return?temp;
????????}

????????
????}

}

深拷貝:上面簡(jiǎn)單的調(diào)用了Object的clone()方法,此時(shí)只是進(jìn)行了淺拷貝,若Monkey里含有對(duì)象成員staff,則用上述方法克隆出的對(duì)象與原對(duì)象指向同一個(gè)對(duì)象staff,顯然有時(shí)候這并不滿足要求。
深拷貝是指:被復(fù)制的對(duì)象的所有變量都含有與原來(lái)對(duì)象相同的值,除去那些引用其它變量的對(duì)象。
在Java中可以利用串行化(Serivalized)來(lái)實(shí)現(xiàn)深拷貝,先使一個(gè)對(duì)象實(shí)現(xiàn)Serializable接口,然后把對(duì)象(對(duì)象的一個(gè)拷貝)寫(xiě)入一個(gè)流中,后再?gòu)牧骼镒x出來(lái),這樣便可重復(fù)創(chuàng)建對(duì)象。
package?prototype;
import?java.util.Date;
import?java.io.*;
public?class?Monkey?implements?Cloneable,Serializable{
????
private?int?height;
????
private?int?weight;
????
private?GoldRingedStaff?staff;?? //GoldRingedStaff必須實(shí)現(xiàn)Serializable接口
????
private?Date?birthDate;
????
????
public?Monkey(){
????????birthDate
=new?Date();
????????staff
=new?GoldRingedStaff();
????}

????????
//深拷貝
????public?Object?deepClone()throws?IOException,ClassNotFoundException{
????????ByteArrayOutputStream?bo
=new?ByteArrayOutputStream();
????????ObjectOutputStream?oo
=new?ObjectOutputStream(bo);
????????oo.writeObject(
this); //寫(xiě)入流中
????????ByteArrayInputStream?bi
=new?ByteArrayInputStream(bo.toByteArray());
????????ObjectInputStream?oi
=new?ObjectInputStream(bi);
????????
return?oi.readObject(); //從流中讀出
????}

????}

使用原型模式,有以下結(jié)論:
?????????1.在運(yùn)行時(shí),可以根據(jù)需要,以復(fù)制的方式增加和刪除類。(登記型原形模式)
???????? 2.可以基于程序條件,在運(yùn)行時(shí)修改一個(gè)類的內(nèi)部數(shù)據(jù)表示。
???????? 3.還可以在運(yùn)行時(shí)指定新的對(duì)象,而無(wú)需創(chuàng)建一系列類和繼承結(jié)構(gòu)。


參考資料:《Java與模式》
????????????????????《Java設(shè)計(jì)模式》
?????????????????? ? http://www.lvjiyong.com/books/DesignPatterns/16.html