日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
設(shè)計(jì)模式-Prototype原型模式

[[400064]]

前言

在設(shè)計(jì)模式的系列文章中,我們前面已經(jīng)寫了工廠模式、單列模式、建造者模式,在針對(duì)創(chuàng)建型模式中,今天想跟大家分享的是原型模式

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的景縣網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

其實(shí)原型模式在我們的代碼中是很常見的,但是又容易被我們所忽視的一種模式,那么什么是原型模式呢?

原型模式其實(shí)就是一種克隆對(duì)象的方法,在我們的編碼時(shí)候是很常見的,比如我們常用的的BeanUtils.copyProperties就是一種對(duì)象的淺copy,其實(shí)現(xiàn)在我們實(shí)例化對(duì)象操作并不是特別耗費(fèi)性能,所以在針對(duì)一些特殊場景我們還是需要克隆那些已經(jīng)實(shí)例化的對(duì)象的:

  • 依賴外部資源或硬件密集型操作,比如數(shù)據(jù)庫查詢,或者一些存在IO操作的場景
  • 獲取相同對(duì)象在相同狀態(tài)的拷貝從而不需要重復(fù)創(chuàng)建獲取狀態(tài)的操作的情況

看下我們的類圖:

在上面的圖中我們可以看出原型模式其實(shí)很簡單:

  • 第一個(gè)是抽象原型(prototype)聲明clone方法,可以是接口可以是基類,在簡單的場景下我們都可以不用基類直接具體類就可以了。
  • 第二個(gè)就是具體原型類(concreteprototype)實(shí)現(xiàn)或者擴(kuò)展clone方法,當(dāng)我們?cè)诰唧w的原型類中的對(duì)象方法時(shí),就會(huì)返回一個(gè)基類的抽象原型對(duì)象

針對(duì)上面理論知識(shí),我們還是實(shí)際的舉一個(gè)例子吧!

舉例

假設(shè)現(xiàn)在我們有這么一種場景,公司搞一場活動(dòng)有五萬個(gè)商品參加此次活動(dòng),我們需要從后臺(tái)能定時(shí)同步每個(gè)商品的銷量,方便我們?yōu)楹竺娴幕顒?dòng)做商品分析,我們要怎么處理這個(gè)銷量同步問題?

首先在這里銷量和庫存都是屬于熱點(diǎn)數(shù)據(jù),但肯定都是相互隔離的因?yàn)閹齑媸且髮?shí)時(shí)性很高的,銷量可以允許有短暫延時(shí),只要能保證數(shù)據(jù)能夠最終一致性就行,所以下單的同時(shí)我們可以根據(jù)一個(gè)MQ去更新我們數(shù)據(jù)庫里的商品銷量。

在我們?nèi)ゲ榭翠N量的時(shí)候我們不能每次都是去查DB所以我們可以通過redis緩存來處理,同時(shí)我們?cè)诰彺嬷杏涗浺幌挛覀儺?dāng)前查詢的更新時(shí)間。

再次查詢時(shí)通過redis數(shù)據(jù)里面的更新時(shí)間,作為查詢條件去查詢DB中的更新時(shí)間大于我們當(dāng)前redis中的記錄時(shí)間,這樣就減少了SQL的掃表的行數(shù)(更新的數(shù)據(jù)與全量數(shù)據(jù)相比,更新的數(shù)據(jù)量還是占少數(shù)的)

基于上面流程我們開始寫demo了

在這里demo中我們先是創(chuàng)建了一個(gè)ItemSold類,以及一個(gè)SkuSold類同時(shí)ItemSold重寫Cloneable里面的clone方法。然后在最后的測試類mian方法中我調(diào)用了clone方法,copy一個(gè)新的商品銷量類。

細(xì)心的同學(xué)在看結(jié)果的時(shí)候不知道有沒有發(fā)現(xiàn)一個(gè)問題?在for循環(huán)里面,我分別打印出來的ItemSold 以及 SkuSold對(duì)象他們的內(nèi)存地址。

復(fù)制出來的SkuSold的內(nèi)存地址居然和原型地址一樣,ItemSold的復(fù)制就和原型地址不一樣了,針對(duì)這個(gè)問題這里我們就要聊聊原型模式的兩種實(shí)現(xiàn)淺拷貝和深拷貝了。

  • 這里說明一下我們?cè)趂or循環(huán)里面是做數(shù)據(jù)convert,一般來說我們不會(huì)引用底層模型來做返回結(jié)果模型,需要做一層轉(zhuǎn)化,來達(dá)到防腐的效果。為了體現(xiàn)深淺拷貝,所以寫的比較簡單,具體還是需要自己根據(jù)實(shí)際情況來做。

淺拷貝和深拷貝

  • 淺拷貝:當(dāng)拷貝對(duì)象只包含簡單的數(shù)據(jù)類型比如int、float 或者不可變的對(duì)象(字符串)時(shí),就直接將這些字段復(fù)制到新的對(duì)象中。而引用的對(duì)象并沒有復(fù)制而是將引用對(duì)象的地址復(fù)制一份給克隆對(duì)象
  • 深拷貝:不管拷貝對(duì)象里面簡單數(shù)據(jù)類型還是引用對(duì)象類型都是會(huì)完全的復(fù)制一份到新的對(duì)象中

舉個(gè)例子這就好比兩兄弟大家買衣服可以一人一套,然后房子大家住在一套房子里(淺拷貝),當(dāng)兩個(gè)人成家立業(yè)了,房子分開了一人一套互不影響(深拷貝)

看完這張圖,大家也就明白了,上面的demo是一個(gè)淺拷貝,那么我們要怎么做才能實(shí)現(xiàn)深拷貝呢?

首先我們先來看下 Java的提供的Cloneable 接口

看接口上面的解釋大致可以理解為:

  • 一個(gè)類實(shí)現(xiàn)了Cloneable接口,來實(shí)現(xiàn)這個(gè)類的clone方法從而可以合法地對(duì)該類實(shí)例進(jìn)行按字段復(fù)制,假設(shè)這個(gè)類沒有實(shí)現(xiàn)Cloneable接口的實(shí)例上調(diào)用Object的clone()方法,則會(huì)導(dǎo)致拋出CloneNotSupporteddException異常。

那么我們這里怎么實(shí)現(xiàn)深拷貝呢?

第一種:在重寫ItemSold里面的clone方法時(shí),再針對(duì)SkuSold也進(jìn)行一次拷貝 (因?yàn)槲覀冞@里時(shí)List對(duì)象,只能是先拿到淺拷貝,再通過淺拷貝的List對(duì)象進(jìn)行遍歷再調(diào)用引用對(duì)象的clone方法來實(shí)現(xiàn)深拷貝)

這里如果引用對(duì)象存在多級(jí)情況下我們可能就要考慮用遞歸了實(shí)現(xiàn),但是代碼看上去就會(huì)復(fù)雜很多了。

第二種:通過序列化把對(duì)象寫入流中再從流中取出來

針對(duì)上面的兩種寫法其實(shí)都是可以實(shí)現(xiàn)的,但是不管用哪種方式,深拷貝都比淺拷貝花時(shí)間和空間,所以還是酌情考慮。其實(shí)在現(xiàn)在已經(jīng)有很多針對(duì)淺拷貝和深拷貝的工具類

  • 深拷貝(deep copy):SerializationUtils
  • 淺拷貝(shallow copy):BeanUtils

思考

針對(duì)上面的業(yè)務(wù)場景我們也可以通過其他的方式統(tǒng)計(jì)商品銷量,可以再通過一個(gè)MQ去增加銷量的同時(shí)再去更新redis緩存,但是需要我們注意的是在針對(duì)一些核心業(yè)務(wù)數(shù)據(jù)和非核心業(yè)務(wù)數(shù)據(jù)盡量不要共用一個(gè)消費(fèi)者組,防止影響核心數(shù)據(jù)的消費(fèi)速率。同時(shí)我們?cè)谧鲈O(shè)計(jì)的時(shí)候多想想這么做有什么優(yōu)點(diǎn),又有什么缺點(diǎn),開發(fā)成本問題等。

其實(shí)在其他的地方我們可以用到原型模式,比如我們?cè)诎l(fā)松活動(dòng)的PUSH通知,針對(duì)平臺(tái)百萬、千萬、甚至上億的用戶發(fā)送通知的時(shí)候通知的內(nèi)容基本都是一樣的只是推送用戶不一樣或者有些特別字段值的小改動(dòng),那我們這里就可以用原型模式來做,同時(shí)開啟多線程來做push,需要注意的是這里的線程安全問題,所以在每個(gè)線程內(nèi)部去做copy對(duì)象。

總結(jié)

原型模式使用起來簡單,但是在我們每次在clone基類或者有引用對(duì)象的時(shí)候需要我們?nèi)バ薷脑蛯?duì)象的clone方法,這不符合我們開閉原則。

在一般情況下是不建議用這種模式的除非創(chuàng)建的對(duì)象成本特別大,或者在一些特殊場景使用,最后針對(duì)一些不常用的模式我不會(huì)詳細(xì)跟大家分享,但是我會(huì)在后面做個(gè)分享總結(jié),后面開始為大家分享行為型模式。

我是敖丙,你知道的越多,你不知道的越多,我們下期見!


分享題目:設(shè)計(jì)模式-Prototype原型模式
文章位置:http://www.dlmjj.cn/article/dphhojc.html