原型模式:通過(guò)new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問(wèn)權(quán)限,則可以使用原型模式。就是java中的克隆技術(shù),以某個(gè)對(duì)象為原型,復(fù)制出新的對(duì)象。顯然,新的對(duì)象具備原型對(duì)象的特點(diǎn)。
優(yōu)勢(shì):效率高(直接克隆,避免了重新執(zhí)行構(gòu)造步驟)。
克隆類似于new,但是不同于new。new創(chuàng)建新的對(duì)象屬性采用的是默認(rèn)值??寺〕龅膶?duì)象的屬性值完全和原型對(duì)象相同。并且克隆出的新對(duì)象改變不會(huì)影響原型對(duì)象。然后,再修改克隆對(duì)象的值。
原型模式實(shí)現(xiàn):
Cloneable接口和clone方法。
Prototype模式中實(shí)現(xiàn)起來(lái)最困難的地方就是內(nèi)存復(fù)制操作,所幸在Java中提供了clone()方法替我們做了絕大部分事情。
淺復(fù)制和深復(fù)制:
例:淺復(fù)制
我們知道,一個(gè)類的定義中包括屬性和方法。屬性用于表示對(duì)象的狀態(tài),方法用于表示對(duì)象所具有的行為。其中,屬性既可以是Java中基本數(shù)據(jù)類型,也可以是引用類型。Java中的淺復(fù)制通常使用clone()方式完成。
當(dāng)進(jìn)淺復(fù)制時(shí),clone函數(shù)返回的是一個(gè)引用,指向的是新的clone出來(lái)的對(duì)象,此對(duì)象與原對(duì)象分別占用不同的堆空間。同時(shí),復(fù)制出來(lái)的對(duì)象具有與原對(duì)象一致的狀態(tài)。
此處對(duì)象一致的狀態(tài)是指:復(fù)制出的對(duì)象與原對(duì)象中的屬性值完全相等==。
由輸出的結(jié)果可以驗(yàn)證說(shuō)到的結(jié)論。由此我們發(fā)現(xiàn):雖然復(fù)制出來(lái)的對(duì)象重新在堆上開辟了內(nèi)存空間,但是,對(duì)象中各屬性確保持相等。對(duì)于基本數(shù)據(jù)類型很好理解,但對(duì)于引用數(shù)據(jù)類型來(lái)說(shuō),則意味著此引用類型的屬性所指向的對(duì)象本身是相同的, 并沒(méi)有重新開辟內(nèi)存空間存儲(chǔ)。換句話說(shuō),引用類型的屬性所指向的對(duì)象并沒(méi)有復(fù)制。
由此,我們將其稱之為淺復(fù)制。當(dāng)復(fù)制后的對(duì)象的引用類型的屬性所指向的對(duì)象也重新得以復(fù)制,此時(shí),稱之為深復(fù)制。
二、深復(fù)制:
Java中的深復(fù)制一般是通過(guò)對(duì)象的序列化和反序列化得以實(shí)現(xiàn)。序列化時(shí),需要實(shí)現(xiàn)Serializable接口。
下面還是以Book為例,看下深復(fù)制的一般實(shí)現(xiàn)過(guò)程:
1.定義Book類和Author類(注意:不僅Book類需要實(shí)現(xiàn)Serializable接口,Author同樣也需要實(shí)現(xiàn)Serializable接口!!):
從輸出結(jié)果中可以看出,深復(fù)制不僅在堆內(nèi)存上開辟了空間以存儲(chǔ)復(fù)制出的對(duì)象,甚至連對(duì)象中的引用類型的屬性所指向的對(duì)象也得以復(fù)制,重新開辟了堆空間存儲(chǔ)。
至此:設(shè)計(jì)模式中的創(chuàng)建型模式總結(jié)完畢,一共有五種創(chuàng)建型模式,分別為:?jiǎn)卫J剑⊿ingleTon)、建造者模式(Builder)、工廠方法模式(Factory Method)、抽象工廠模式(Abstract Factory)和原型模式(Prototype)。每種模式適用于不同的場(chǎng)景,具體應(yīng)用時(shí)需注意區(qū)分。
publicBook deepClone()throwsIOException, ClassNotFoundException{8//寫入當(dāng)前對(duì)象的二進(jìn)制流9ByteArrayOutputStream bos =newByteArrayOutputStream();10ObjectOutputStream oos =newObjectOutputStream(bos);11oos.writeObject(this);1213//讀出二進(jìn)制流產(chǎn)生的新對(duì)象14ByteArrayInputStream bis =newByteArrayInputStream(bos.toByteArray());15ObjectInputStream ois =newObjectInputStream(bis);16return(Book) ois.readObject();17}
開發(fā)中的應(yīng)用場(chǎng)景:
——原型模式很少單獨(dú)出現(xiàn),一般是和工廠方法模式一起出現(xiàn),通過(guò)clone的方法創(chuàng)建一個(gè)對(duì)象,然后由工廠方法提供給調(diào)用者。
spring中bean的創(chuàng)建實(shí)際就是兩種:?jiǎn)卫J胶驮湍J?。(?dāng)然,原型模式需要和工廠模式搭配起來(lái))
總結(jié):
創(chuàng)建者模式:都是用來(lái)幫助我們創(chuàng)建對(duì)象的。
——單例模式:
保證一個(gè)類只有一個(gè)實(shí)例,并且提供一個(gè)訪問(wèn)該實(shí)例的全局訪問(wèn)點(diǎn)。
——工廠模式:
簡(jiǎn)單工廠模式:用來(lái)生產(chǎn)同一等級(jí)結(jié)構(gòu)中的任意產(chǎn)品。(對(duì)于增加新的產(chǎn)品,需要修改已有代碼)
工廠方法模式:用來(lái)生產(chǎn)同一等級(jí)結(jié)構(gòu)中的固定產(chǎn)品。(支持增加任意產(chǎn)品)
抽象工廠模式:用來(lái)生產(chǎn)不同產(chǎn)品族的全部產(chǎn)品。(對(duì)于增加新的產(chǎn)品,無(wú)能為力;支持增加產(chǎn)品族)
——建造者模式:
分離了對(duì)象子組件的單獨(dú)構(gòu)造(由Builder來(lái)負(fù)責(zé))和裝配(由Director負(fù)責(zé)),從而可以構(gòu)造出復(fù)雜的對(duì)象。
——原型模式:
通過(guò)new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問(wèn)權(quán)限,則可以使用原型模式。