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