您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Prototype原型模式怎么實(shí)現(xiàn)”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
Prototype(原型模式)
Prototype(原型模式)屬于創(chuàng)建型模式,既不是工廠也不是直接 New,而是以拷貝的方式創(chuàng)建對(duì)象。
意圖:用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。
舉例子
如果看不懂上面的意圖介紹,沒(méi)有關(guān)系,設(shè)計(jì)模式需要在日常工作里用起來(lái),結(jié)合例子可以加深你的理解,下面我準(zhǔn)備了三個(gè)例子,讓你體會(huì)什么場(chǎng)景下會(huì)用到這種設(shè)計(jì)模式。
做鑰匙
很顯然,為了房屋安全,要盡量做到一把鑰匙只能開(kāi)一扇門(mén),每把鑰匙結(jié)構(gòu)都多多少少不一樣,卻又很相似,做鑰匙的人按照你給的鑰匙一模一樣做一個(gè)新的,這屬于什么模式呢?
兩種狀態(tài)表
當(dāng)網(wǎng)站做不停機(jī)維護(hù)時(shí),假設(shè)維護(hù)內(nèi)容是給每個(gè)高級(jí)會(huì)員賬戶多打 100 元現(xiàn)金,現(xiàn)在需要改數(shù)據(jù)庫(kù)表。已知:
數(shù)據(jù)庫(kù)表有幾千萬(wàn)條數(shù)據(jù),其中高級(jí)會(huì)員有幾千位,為了方便調(diào)用已經(jīng)緩存在中間層了,且數(shù)據(jù)庫(kù)對(duì)應(yīng) ID 更新后對(duì)應(yīng)緩存也會(huì)更新。
幾千條數(shù)據(jù)修改語(yǔ)句執(zhí)行完需要幾分鐘,這幾分鐘內(nèi)無(wú)法接受用戶數(shù)據(jù)不同步的問(wèn)題。
一種常見(jiàn)的做法是,我們生成一份高級(jí)會(huì)員列表的拷貝,代替數(shù)據(jù)庫(kù)緩存的結(jié)果,數(shù)據(jù)庫(kù)只要讀到對(duì)應(yīng)會(huì)員 ID 就從拷貝列表中獲取,數(shù)據(jù)表新增一列狀態(tài)標(biāo)志,操作完后這個(gè)拷貝移除,更新高級(jí)會(huì)員緩存。
但是如何生成高級(jí)會(huì)員列表拷貝呢?如果直接從幾千萬(wàn)條用戶數(shù)據(jù)中重新查詢,會(huì)有較高的數(shù)據(jù)庫(kù)查詢成本。
模版組件
通用搭建系統(tǒng)中,我們可以將某個(gè)拖拽到頁(yè)面的區(qū)塊設(shè)置為 “模版”,這個(gè)模版可以作為一個(gè)新組件被重新拖拽到任意為止,實(shí)例化任意次。實(shí)際上,這是一種分段式復(fù)制粘貼,你會(huì)如何實(shí)現(xiàn)這個(gè)功能呢?
意圖解釋
解決上面問(wèn)題的辦法都很簡(jiǎn)單,就是基于已有對(duì)象進(jìn)行復(fù)制即可,效率比 New 一個(gè),或者工廠模式都要高。
意圖:用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并且通過(guò)拷貝這些原型創(chuàng)建新的對(duì)象。
所謂原型實(shí)例,就是被選為拷貝模版的那個(gè)對(duì)象,比如做鑰匙例子中,你給老板的樣板鑰匙;兩種狀態(tài)表中的已有緩存高級(jí)會(huì)員列表;模版組件中選中的那個(gè)組件。然后,通過(guò)拷貝這些原型創(chuàng)建你想要的對(duì)象即可。
我們抽象思考一下,如果每把鑰匙都遵循 Prototype 接口,提供了 clone() 方法以復(fù)制自己,那就可以快速?gòu)?fù)制任意一把鑰匙。鑰匙工廠可無(wú)法解決每把鑰匙不一樣的問(wèn)題,我們要的就是和某個(gè)鑰匙一模一樣的副本,復(fù)制一份鑰匙最簡(jiǎn)單。
高級(jí)會(huì)員狀態(tài)表例子中,查詢數(shù)據(jù)庫(kù)的成本是高昂的,但如果僅僅復(fù)制已經(jīng)查詢好的列表,時(shí)間可以忽略不計(jì),因此最經(jīng)濟(jì)的方案是直接復(fù)制,而不是通過(guò)工廠模式重新連接數(shù)據(jù)庫(kù)并執(zhí)行查詢。
模版組件更是如此,我們根本沒(méi)有定義那么多組件實(shí)例的基類(lèi),只要每個(gè)組件提供一個(gè) clone() 函數(shù),就可以立即復(fù)制任意組件實(shí)例,這無(wú)疑是最經(jīng)濟(jì)實(shí)惠的方案。
看到這里,你應(yīng)該知道了,原型模式的精髓是對(duì)象要提供 clone() 方法,而這個(gè) clone() 方法實(shí)現(xiàn)難度有高有低。
一般來(lái)說(shuō),原型模式的拷貝建議用深拷貝,畢竟新對(duì)象最好不要影響到舊對(duì)象,但是在深拷貝性能問(wèn)題較大的情況下,可以考慮深淺拷貝結(jié)合,也就是將在新對(duì)象中,不會(huì)修改的數(shù)據(jù)使用淺拷貝,可能被修改的數(shù)據(jù)使用深拷貝。
結(jié)構(gòu)圖
Client 是發(fā)出指令的客戶端,Prototype 是一個(gè)接口,描述了一個(gè)對(duì)象如何克隆自身,比如必須擁有 clone() 方法,而 ConcretePrototype 就是克隆具體的實(shí)現(xiàn),不同對(duì)象有不同的實(shí)現(xiàn)來(lái)拷貝自身。
代碼例子
下面例子使用 typescript 編寫(xiě)。
class Component implements Prototype {
/**
* 組件名
*/
private name: string
/**
* 組件版本
*/
private version: string
/**
* 拷貝自身
*/
public clone = () => {
// 構(gòu)造函數(shù)省略了,大概就是傳遞 name 和 version
return new Component(this.name, this.version)
}
}
我們可以看到,實(shí)現(xiàn)了 Prototype 接口的 Component 必須實(shí)現(xiàn) clone 方法,這樣任意組件在執(zhí)行復(fù)制時(shí),就可以直接調(diào)用 clone 函數(shù),而不用關(guān)心每個(gè)組件不同的實(shí)現(xiàn)方式了。
從這就能看出,原型模式與 Factory 與 Builder 模式還是有類(lèi)似之處的,在隱藏創(chuàng)建對(duì)象細(xì)節(jié)這一點(diǎn)上。
使用的時(shí)候,我們就可以這樣創(chuàng)建一個(gè)新對(duì)象:
const newComponent = oldComponent.clone()
這里有兩個(gè)注意點(diǎn):一般來(lái)說(shuō),如果要二次修改生成的對(duì)象,不建議給 clone 函數(shù)加參數(shù),因?yàn)檫@樣會(huì)導(dǎo)致接口的不一致。 我們可以為對(duì)象實(shí)例提供一些 set 函數(shù)進(jìn)行二次修改。另外,clone 函數(shù)要考慮性能,就像前面說(shuō)過(guò)的,可以考慮深淺拷貝結(jié)合的方式,同時(shí)要注意當(dāng)對(duì)象存在引用關(guān)系甚至循環(huán)引用時(shí),甚至不一定能實(shí)現(xiàn)拷貝函數(shù)。
弊端
每個(gè)設(shè)計(jì)模式必有弊端,但就像每一期都說(shuō)的,有弊端不代表設(shè)計(jì)模式不好用,而是指在某種場(chǎng)景喜愛(ài)存在問(wèn)題,我們只要規(guī)避這些場(chǎng)景,在合理的場(chǎng)景使用對(duì)應(yīng)設(shè)計(jì)模式即可。
原型模式的弊端:
每個(gè)類(lèi)都要實(shí)現(xiàn) clone 方法,對(duì)類(lèi)的實(shí)現(xiàn)是有一定入侵的,要修改已有類(lèi)時(shí),違背了開(kāi)閉原則。
當(dāng)類(lèi)又調(diào)用了其他對(duì)象時(shí),如果要實(shí)現(xiàn)深拷貝,需要對(duì)應(yīng)對(duì)象也實(shí)現(xiàn) clone 方法,整體鏈路可能會(huì)特別長(zhǎng),實(shí)現(xiàn)起來(lái)比較麻煩。
“Prototype原型模式怎么實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。