一.定義
原型模式(Prototype Pattern)的簡單程度僅次于單例模式和迭代器模式。正是由于簡單,使用的場景才非常地多,其定義如下:
Specify the kinds of objects to create using a prototypical instance, and create new objects by copyingthis prototype.(用原型實例指定創(chuàng)建對象的種類,并且通過拷貝這些原型創(chuàng)建新的對象。)
實際的類圖模板如下:
原型模式的通用源碼如下:
實現(xiàn)一個接口,然后重寫clone方法,就完成了原型模式!
二.例子
用一個個性化服務(wù)賬單,來說明什么是原型模式,看一則小故事.
現(xiàn)在電子賬單越來越流行了,比如你的信用卡,每到月初的時候銀行就會發(fā)–份電子郵件給你,說你這個月消費了多少,什么時候消費的,積分是多少等,這是每個月發(fā)一次。還有一種也是銀行發(fā)的郵件你肯定非常有印象:廣告信,現(xiàn)在各大銀行的信用卡部門都在拉攏客戶,電子郵件是一種廉價、快捷的通信方式,你用紙質(zhì)的廣告信那個費用多高呀,比如我行今天推出一個信用卡刷卡抽獎活動,通過電子賬單系統(tǒng)可以一個晚上發(fā)送給600萬客戶,為什么要用電子賬單系統(tǒng)呢?直接找個發(fā)垃圾郵件的工具不就解決問題了嗎?是個好主意,但是這個方案在金融行業(yè)是行不通的,為什么?因為銀行發(fā)送該類郵件是有要求的:
- 個性化服務(wù)
一般銀行都要求個性化服務(wù),發(fā)過去的郵件上總有一些個人信息吧,比如“XX先生”,“XX女士”等。 - 遞送成功率
郵件的遞送成功率有一定的要求,由于大批量地發(fā)送郵件會被接收方郵件服務(wù)器誤認(rèn)是垃圾郵件,因此在郵件頭要增加一些偽造數(shù)據(jù),以規(guī)避被反垃圾郵件引擎誤認(rèn)為是垃圾郵件。
從這兩方面考慮廣告信的發(fā)送也是電子賬單系統(tǒng)(電子賬單系統(tǒng)一般包括:賬單分析、賬單生成器、廣告信管理、發(fā)送隊列管理、發(fā)送機(jī)、退信處理、報表管理等)的一個子功能,我們今天就來考慮一下廣告信這個模塊是怎么開發(fā)的。那既然是廣告信,肯定需要一個模版,然后再從數(shù)據(jù)庫中把客戶的信息一個一個地取出,放到模板中生成一份完整的郵件,然后扔給發(fā)送機(jī)進(jìn)行發(fā)送處理,類圖如圖所示
廣告模板代碼
郵件類代碼
Mail類就是一個業(yè)務(wù)對象,雖然比較長,還是比較簡單的。我們再來看業(yè)務(wù)場景類是如何對郵件繼續(xù)處理的,代碼如下:
由于是隨機(jī)數(shù),每次運行都有所差異,不管怎么樣,我們這個電子賬單發(fā)送程序是編寫出來了,也能正常發(fā)送。我們再來仔細(xì)地想想,這個程序是否有問題?Look here,這是一個線程在運行,也就是你發(fā)送的是單線程的,那按照一封郵件發(fā)出去需要0.02秒(夠小了,你還要到數(shù)據(jù)庫中取數(shù)據(jù)呢),600萬封郵件需要33個小時,也就是一個整天都發(fā)送不完,今天的不發(fā)送完,明天的賬單又產(chǎn)生了,日積月累,激起甲方人員一堆抱怨,那怎么辦?
好辦,把sendMail修改為多線程,但是只把sendMail修改為多線程還是有問題的呀,產(chǎn)生第一封郵件對象,放到線程1中運行,還沒有發(fā)送出去,線程2也啟動了,直接就把郵件對象mail的收件人地址和稱謂修改掉了,線程不安全了。說到這里,你會說這有N多種解決辦法,其中一種是使用一種新型模式來解決這個問題:通過對象的復(fù)制功能來解決這個問題,類圖稍作修改,如圖所示
修改后的郵件類
修改后的場景類
運行結(jié)果不變,一樣完成了電子廣告信的發(fā)送功能,而且sendMail即使是多線程也沒有關(guān)系。注意,看Client類中的粗體字mail.clone()這個方法,把對象復(fù)制一份,產(chǎn)生一個新的對象,和原有對象一樣,然后再修改細(xì)節(jié)的數(shù)據(jù),如設(shè)置稱謂、設(shè)置收件人地址等。這種不通過new關(guān)鍵字來產(chǎn)生一個對象,而是通過對象復(fù)制來實現(xiàn)的模式就叫做原型模式。文章來源:http://www.zghlxwxcb.cn/news/detail-492177.html
三.結(jié)論
優(yōu)點
- 性能優(yōu)良
原型模式是在內(nèi)存二進(jìn)制流的拷貝,要比直接new一個對象性能好很多,特別是要在一個循環(huán)體內(nèi)產(chǎn)生大量的對象時,原型模式可以更好地體現(xiàn)其優(yōu)點。 - 逃避構(gòu)造函數(shù)的約束
這既是它的優(yōu)點也是缺點,直接在內(nèi)存中拷貝,構(gòu)造函數(shù)是不會執(zhí)行的,優(yōu)點就是減少了約束,缺點也是減少了約束,需要大家在實際應(yīng)用時考慮。
使用場景
- 資源優(yōu)化場景
類初始化需要消化非常多的資源,這個資源包括數(shù)據(jù)、硬件資源等。 - 性能和安全要求的場景
通過new產(chǎn)生一個對象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問權(quán)限,則可以使用原型模式。 - 一個對象多個修改者的場景
一個對象需要提供給其他對象訪問,而且各個調(diào)用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調(diào)用者使用。
在實際項目中,原型模式很少單獨出現(xiàn),一般是和工廠方法模式一起出現(xiàn),通過clone的方法創(chuàng)建一個對象,然后由工廠方法提供給調(diào)用者。原型模式已經(jīng)與Java融為一體,大家可以隨手拿來使用。文章來源地址http://www.zghlxwxcb.cn/news/detail-492177.html
到了這里,關(guān)于軟件設(shè)計模式之原型模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!