Prototype-原型模式
- 原型模式: 通過原型的實(shí)例來(lái)指定創(chuàng)建對(duì)象的類型,然后通過拷貝來(lái)創(chuàng)建更多同類型的對(duì)象
-
原型模式的特點(diǎn):
- 原型模式屬于創(chuàng)建型模式
- 原型模式要求原型類實(shí)現(xiàn)拷貝自身的接口,這樣就可以通過拷貝原型的實(shí)例來(lái)創(chuàng)建新的對(duì)象
- 原型模式拷貝原型實(shí)例創(chuàng)建的新對(duì)象不需要關(guān)心對(duì)象本身的類型,只需要實(shí)現(xiàn)原型實(shí)例拷貝自身的方法,就可以通過自定義的拷貝方法來(lái)創(chuàng)建新的對(duì)象,不需要通過new創(chuàng)建新的對(duì)象
原型模式的實(shí)現(xiàn)方式
- 原型模式主要用于對(duì)象的復(fù)制,核心就是抽象原型Prototype
- 抽象原型Prototype需要具備兩個(gè)條件:
-
實(shí)現(xiàn)Clonable接口:
- Clonable接口的作用是在運(yùn)行時(shí)通知JVM可以安全地在實(shí)現(xiàn)Clonable接口的類上使用clone方法
- 在JVM中,只有實(shí)現(xiàn)了Clonable接口的類才可以拷貝,否則會(huì)拋出CloneNotSupportedException異常
-
重寫Object類中的clone方法:
- 所有類的父類都是Object類 ,Object類中有clone() 方法用于返回一個(gè)拷貝的對(duì)象,但是方法的作用域是protected, 一般類無(wú)法進(jìn)行調(diào)用
- 抽象原型Prototype將clone() 方法的作用域修改為public類型
-
實(shí)現(xiàn)Clonable接口:
-
原型模式的適用場(chǎng)景:
- 在需要重復(fù)創(chuàng)建相似的對(duì)象時(shí)可以使用原型模式,即只是個(gè)別的幾個(gè)屬性不同時(shí)
- 直接創(chuàng)建對(duì)象的成本損耗大.比如初始化時(shí)間長(zhǎng),CPU占用大,網(wǎng)絡(luò)資源占用過多,需要優(yōu)化資源等
- 直接創(chuàng)建一個(gè)對(duì)象后還需要準(zhǔn)備大量的數(shù)據(jù)以及訪問權(quán)限時(shí),需要提高性能或者安全性
- 系統(tǒng)中大量使用該類對(duì)象,且各個(gè)調(diào)用者都需要給對(duì)象的屬性重新賦值
-
原型模式有兩種實(shí)現(xiàn)方式:
- 簡(jiǎn)單實(shí)現(xiàn)方式
- 登記實(shí)現(xiàn)方式
簡(jiǎn)單實(shí)現(xiàn)方式
在這里插入圖片描述
- 原型模式的簡(jiǎn)單實(shí)現(xiàn)方式包含三個(gè)角色:
- 抽象原型Prototype: 抽象原型類.給出所有的具體原型所需要實(shí)現(xiàn)的拷貝方法的接口或者抽象類
- 具體原型ConcretePrototype: 用于拷貝的原型實(shí)例.實(shí)現(xiàn)了抽象原型Prototype所要求的接口
- 客戶Client: 客戶端Client用來(lái)請(qǐng)求創(chuàng)建新的對(duì)象
原型管理器實(shí)現(xiàn)方式
在這里插入圖片描述
- 原型模式可以擴(kuò)展成為帶有原型管理器的原型模式:
- 在原型模式的基礎(chǔ)上增加了新的原型管理器PrototypeManager類
- 原型管理器PrototypeManager類中使用HashMap保存多個(gè)復(fù)制的原型對(duì)象
- 客戶端Client類可以通過原型管理器中的get(String id) 方法獲取復(fù)制的原型對(duì)象
原型模式注意點(diǎn)
-
原型模式不會(huì)調(diào)用類的構(gòu)造方法:
- 原型模式通過Object類的clone() 方法拷貝對(duì)象,是直接在內(nèi)存中拷貝原型實(shí)例的數(shù)據(jù),所以不會(huì)調(diào)用類的構(gòu)造方法
- 類的構(gòu)造方法不會(huì)執(zhí)行并且訪問權(quán)限對(duì)原型模式無(wú)效.因?yàn)閱卫J街械膶㈩惖臉?gòu)造方法設(shè)置為private類型,但是clone() 方法是無(wú)視構(gòu)造方法的權(quán)限的.因此原型模式是與單例模式相互沖突的,所以要特別注意原型模式不可以和單例模式一起使用
-
深拷貝與淺拷貝問題:
- 原型模式通過Object類的clone() 方法拷貝對(duì)象時(shí)只會(huì)拷貝對(duì)象的基本數(shù)據(jù)類型以及對(duì)應(yīng)的封裝類型和值類型的String類型,不會(huì)拷貝數(shù)組,容器對(duì)象,引用對(duì)象等.這就是淺拷貝
- 如果要實(shí)現(xiàn)深拷貝,需要將原型模式中的數(shù)組,容器對(duì)象和引用對(duì)象另行拷貝
原型模式總結(jié)
- 原型模式本省比較簡(jiǎn)單,易于實(shí)現(xiàn).主要是重寫Object中的clone() 方法,根據(jù)要求實(shí)現(xiàn)淺拷貝或者是深拷貝
- 原型模式的重點(diǎn)在淺拷貝和深拷貝的理解和運(yùn)用
原型模式優(yōu)點(diǎn)
- 使用原型模式創(chuàng)建對(duì)象比直接使用new創(chuàng)建對(duì)象的性能要好: 因?yàn)?strong>Object中的clone() 方法是一個(gè)本地native方法,直接操作內(nèi)存中的二進(jìn)制流.尤其在拷貝大對(duì)象時(shí),性能提升明顯
- 使用原型模式簡(jiǎn)化了對(duì)象的創(chuàng)建: 通過使用原型模式可以讓對(duì)象的創(chuàng)建像復(fù)制粘貼一樣簡(jiǎn)單
- 可以使用深拷貝的方式保存對(duì)象的狀態(tài): 通過使用原型模式拷貝對(duì)象,并將狀態(tài)保存起來(lái),可以簡(jiǎn)化對(duì)象的創(chuàng)建過程,以便在需要時(shí)使用,可以輔助實(shí)現(xiàn)撤銷的操作
原型模式缺點(diǎn)
- 原型模式需要為每一個(gè)類配置一個(gè)clone() 方法
- clone() 方法在每個(gè)類的內(nèi)部,當(dāng)對(duì)已有類進(jìn)行重構(gòu)時(shí),需要修改代碼,違背了開閉原則
- 實(shí)現(xiàn)深拷貝較為復(fù)雜,而且當(dāng)對(duì)象之間存在多重嵌套時(shí),為了實(shí)現(xiàn)深拷貝,需要每一層對(duì)象對(duì)應(yīng)的類都必須支持深拷貝,實(shí)現(xiàn)比較復(fù)雜