<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          電商系統(tǒng)設(shè)計(jì)模式實(shí)戰(zhàn)

          共 5320字,需瀏覽 11分鐘

           ·

          2022-05-22 22:01

          點(diǎn)擊下方“IT牧場(chǎng)”,選擇“設(shè)為星標(biāo)”

          原文?https://www.toutiao.com/article/7095945904498147848



          1 代理模式

          案例:根據(jù)文件類型,將文件存儲(chǔ)到不同服務(wù)

          代理模式:給一個(gè)對(duì)象創(chuàng)建一個(gè)代理對(duì)象,通過(guò)代理對(duì)象可以使用該對(duì)象的功能。

          CGLib和JDK是代理模式實(shí)現(xiàn)的技術(shù)方案。

          1.1 文件服務(wù)應(yīng)用

          代理模式的應(yīng)用場(chǎng)景除了代碼級(jí)別,還可以將代理模式遷移到應(yīng)用以及架構(gòu)級(jí)別,如下圖文件上傳代理服務(wù),針對(duì)一些圖片小文件,我們可以直接把文件存儲(chǔ)到FastDFS服務(wù),針對(duì)大文件,例如商品視頻介紹,我們可以把它存儲(chǔ)到第三方OSS。

          用戶通過(guò)文件上傳代理服務(wù)可以間接訪問(wèn)OSS和本地FastDFS,這種分布式海量文件管理解決方案,這里不僅在代碼層面充分運(yùn)用了代理模式,在架構(gòu)層面也充分運(yùn)用了代理模式。

          1.2 分布式文件代理服務(wù)器實(shí)現(xiàn)

          1.2.1 實(shí)現(xiàn)分析

          基于代理模式,我們實(shí)現(xiàn)文件上傳分別路由到 aliyunOSS 和 FastDFS ,用例圖如下:

          講解:

          1、FileUpload抽象接口,定義了文件上傳方法,分別給它寫了2種實(shí)現(xiàn)。

          2、AliyunOSSFileUpload是將文件上傳到aliyunOSS,主要上傳mp4和avi的視頻大文件。

          3、FastdfsFileUpoad是將文件上傳到FastDFS,主要上傳png/jpg等圖片小文件。

          4、FileUploadProxy是代理對(duì)象,供用戶訪問(wèn),調(diào)用了FileUpload的文件上傳方法,為用戶提供不同文件上傳調(diào)用。

          5、FileController是控制器,用于接收用戶提交的文件,并調(diào)用代理FileUploadProxy實(shí)現(xiàn)文件上傳。

          1.2.2 代碼實(shí)現(xiàn)

          bootstrap.yml配置:

          FileUpload接口定義:

          AliyunOSSFileUpload實(shí)現(xiàn):


          FastdfsFileUpoad實(shí)現(xiàn):

          FileUploadProxy代理實(shí)現(xiàn):

          FileController控制器實(shí)現(xiàn)

          2 享元模式

          定義:運(yùn)用共享技術(shù)來(lái)有效地支持大量細(xì)粒度對(duì)象的復(fù)用。它通過(guò)共享已經(jīng)存在的對(duì)象來(lái)大幅度減少需要?jiǎng)?chuàng)建的對(duì)象數(shù)量、避免大量相似類的開銷,從而提高系統(tǒng)資源的利用率。

          享元模式和單利的區(qū)別:

          單例是對(duì)象只能自己創(chuàng)建自己,整個(gè)應(yīng)用中只有1個(gè)對(duì)象

          享元模式根據(jù)需要共享,不限制被誰(shuí)創(chuàng)建(有可能有多個(gè)對(duì)象實(shí)例)

          優(yōu)點(diǎn):

          特定環(huán)境下,相同對(duì)象只要保存一份,這降低了系統(tǒng)中對(duì)象的數(shù)量,從而降低了系統(tǒng)中細(xì)粒度對(duì)象給內(nèi)存帶來(lái)的壓力。

          缺點(diǎn):

          為了使對(duì)象可以共享,需要將一些不能共享的狀態(tài)外部化,這將增加程序的復(fù)雜性

          2.1 享元模式實(shí)戰(zhàn)

          案例:用戶下單,會(huì)話共享

          2.1.1 會(huì)話跟蹤分析

          會(huì)話跟蹤,如果是傳統(tǒng)項(xiàng)目用Session或者是Cookie,全項(xiàng)目通用,但在微服務(wù)項(xiàng)目中,不用Session也不用Cookie,所以想要在微服務(wù)項(xiàng)目中實(shí)現(xiàn)會(huì)話跟蹤,是有一定難度的。

          當(dāng)前微服務(wù)項(xiàng)目中,身份識(shí)別的主流方法是前端將用戶令牌存儲(chǔ)到請(qǐng)求頭中,每次請(qǐng)求將請(qǐng)求頭中的令牌攜帶到后臺(tái),后臺(tái)每次從請(qǐng)求頭中獲取令牌來(lái)識(shí)別用戶身份。

          我們?cè)陧?xiàng)目操作過(guò)程中,很多地方都會(huì)用到用戶身份信息,比如下訂單的時(shí)候,要知道當(dāng)前訂單屬于哪個(gè)用戶,記錄下單關(guān)鍵日志的時(shí)候,需要記錄用戶操作的信息以及用戶信息,關(guān)鍵日志記錄我們一般用AOP進(jìn)行攔截操作,此時(shí)沒(méi)法直接把用戶身份信息傳給AOP。這個(gè)時(shí)候我們可以利用享元模式實(shí)現(xiàn)用戶會(huì)話信息共享操作。操作流程如下圖:

          2.1.2 會(huì)話共享案例實(shí)現(xiàn)

          基于上面的分析,我們采用享元模式實(shí)現(xiàn)用戶會(huì)話共享操作,要解決如下幾個(gè)問(wèn)題:

          定義共享組件:LogComponent

          LogComponent 里面定義了每個(gè)線程中不變的用戶身份信息 username 、 role 、 sex ,其他的是可能存在變化的數(shù)據(jù),例如用于做日志記錄的 methodName 、 message 。

          享元組件邏輯操作對(duì)象:SupplementSource

          SupplementSource 該對(duì)象主要用于給當(dāng)前線程填充共享數(shù)據(jù),以及變更訪問(wèn)方法和訪問(wèn)信息等信息的邏輯操作,代碼如下:

          多線程安全控制:ThreadUserLog

          每個(gè)線程請(qǐng)求的時(shí)候,我們需要保障會(huì)話安全,比如A線程訪問(wèn)和B線程訪問(wèn),他們的用戶會(huì)話身份不能因?yàn)椴l(fā)原因而發(fā)生混亂。這里我們可以采用ThreadLocal來(lái)實(shí)現(xiàn)。我們創(chuàng)建一個(gè) ThreadUserLog 對(duì)象,并在該對(duì)象中創(chuàng)建ThreadLocal 用戶存儲(chǔ)每個(gè)線程的會(huì)話信息,并實(shí)現(xiàn) ThreadLocal 的操作,代碼如下:


          線程會(huì)話初始化:AuthorizationInterceptor

          AuthorizationInterceptor 攔截器的作用是用于初始化用戶訪問(wèn)的時(shí)候用戶的身份信息,并將身份信息存儲(chǔ)到ThreadUserLog 的 ThreadLocal 中,在用戶訪問(wèn)方法結(jié)束,銷毀 ThreadUserLog 的 ThreadLocal 中會(huì)話,代碼如下:


          創(chuàng)建 MvcConfig 來(lái)配置攔截器 AuthorizationInterceptor ,代碼如下:


          共享信息使用:

          ①AOP記錄日志:創(chuàng)建AOP切面類 LogAspect 用于記錄日志,代碼如下:


          ②添加訂單獲取用戶信息:在添加訂單方法 OrderServiceImpl.add(Order order) 中,從ThreadUserLog中獲取用戶會(huì)話,并填充給Order,代碼如下

          添加訂單,日志輸出可以看到調(diào)用添加訂單和修改庫(kù)存時(shí),都記錄了日志,并且獲取了用戶會(huì)話,效果如下:

          加的訂單數(shù)據(jù)庫(kù)數(shù)據(jù)中也擁有用戶信息,效果如下:

          3 裝飾著模式

          定義:動(dòng)態(tài)的向一個(gè)現(xiàn)有的對(duì)象添加新的功能,同時(shí)又不改變其結(jié)構(gòu)。它屬于結(jié)構(gòu)型模式。

          優(yōu)點(diǎn):裝飾類和被裝飾類可以獨(dú)立發(fā)展,不會(huì)相互耦合,裝飾模式是繼承的一個(gè)替代模式,裝飾模式可以動(dòng)態(tài)擴(kuò)展一個(gè)實(shí)現(xiàn)類的功能

          缺點(diǎn):多層裝飾比較復(fù)雜。

          3.1 裝飾者模式實(shí)戰(zhàn)

          案例:結(jié)算價(jià)格計(jì)算,根據(jù)不同價(jià)格嵌套運(yùn)算

          在訂單提交的時(shí)候,訂單價(jià)格和結(jié)算價(jià)格其實(shí)是兩碼事,訂單價(jià)格是當(dāng)前商品成交價(jià)格,而結(jié)算價(jià)格是用戶最終需要支付的金額,最終支付的金額并不是一成不變,它也并不是商品成交價(jià)格,能改變結(jié)算價(jià)格的因素很多,比如滿100減10元,VIP用戶再減5塊。訂單結(jié)算金額計(jì)算我們就可以采用裝飾者模式。

          3.1.2 裝飾者模式價(jià)格運(yùn)算實(shí)現(xiàn)

          實(shí)現(xiàn)思路分析:

          基礎(chǔ)接口:創(chuàng)建接口 MoneySum ,該接口只用于定義計(jì)算訂單金額的方法。

          訂單金額計(jì)算類:創(chuàng)建類 OrderPayMoneyOperation 實(shí)現(xiàn)訂單金額的計(jì)算。

          裝飾者類:創(chuàng)建裝飾者類 DecoratorMoneySum 供其他類擴(kuò)展。


          滿100減10元價(jià)格計(jì)算:創(chuàng)建類 FullMoneySum 擴(kuò)展裝飾者類,實(shí)現(xiàn)滿減價(jià)格計(jì)算。


          VIP優(yōu)惠10元價(jià)格計(jì)算:創(chuàng)建類 VipMoneySum ,實(shí)現(xiàn)VIP優(yōu)惠計(jì)算。

          支付金額計(jì)算修改 OrderServiceImpl 的 add() 方法,添加訂單金額以及訂單支付金額的計(jì)算功能,代碼如下:

          測(cè)試效果:

          測(cè)試數(shù)據(jù)中,我們選擇購(gòu)買1件商品,當(dāng)前登錄用戶為王五,擁有5個(gè)金幣,當(dāng)前購(gòu)買的商品id=1,商品單價(jià)是150元,滿減100,VIP優(yōu)惠5元,最終支付135元。

          測(cè)試生成的訂單如下:

          不僅如此,我們可以隨時(shí)撤掉滿減和Vip優(yōu)惠功能。

          4 策略模式

          定義:策略模式是對(duì)算法的包裝,把使用算法的責(zé)任和算法本身分隔開,委派給不同的對(duì)象管理。策略模式通常把一系列的算法包裝到一系列的策略類里面,作為一個(gè)抽象策略類的子類。

          簡(jiǎn)單來(lái)說(shuō)就是就定義一個(gè)策略接口,子類策略去實(shí)現(xiàn)該接口去定義不同的策略。然后定義一個(gè)環(huán)境(Context,也就是需要用到策略的對(duì)象)類,以策略接口作為成員變量,根據(jù)環(huán)境來(lái)使用具體的策略。

          優(yōu)點(diǎn):

          缺點(diǎn):


          4.1 策略模式實(shí)戰(zhàn)

          案例:結(jié)算價(jià)格計(jì)算,根據(jù)Vip不同等級(jí)進(jìn)行運(yùn)算

          4.1.1 不同VIP優(yōu)惠價(jià)格分析

          用戶在購(gòu)買商品的時(shí)候,很多時(shí)候會(huì)根據(jù)Vip等級(jí)打不同折扣,尤其是在線商城中體現(xiàn)的淋漓盡致。我們這里也基于真實(shí)電商案例來(lái)實(shí)現(xiàn)VIP等級(jí)價(jià)格制:

          4.1.2 代碼實(shí)現(xiàn)

          定義策略接口:Strategy

          定義Vip0策略StrategyVipOne

          定義Vip1策略:?StrategyVipTwo

          定義Vip2策略StrategyVipThree

          定義Vip3策略StrategyVipFour

          定義策略工廠StrategyFactory

          等級(jí)策略配置修改application.yml,將如下策略配置進(jìn)去

          等級(jí)控制修改 UserHandler 添加等級(jí)屬性

          修改 UserHandlerShare 定義等級(jí),代碼如下:

          裝飾者模式中修改 VipMoneySum 的價(jià)格運(yùn)算,代碼如下:

          測(cè)試:

          5 工廠模式

          案例:收銀案例,根據(jù)不同支付方式,選擇不同支付渠道

          定義:定義一個(gè)創(chuàng)建產(chǎn)品對(duì)象的工廠接口,將產(chǎn)品對(duì)象的實(shí)際創(chuàng)建工作推遲到具體子工廠類當(dāng)中。這滿足創(chuàng)建型模式中所要求的“創(chuàng)建與使用相分離”的特點(diǎn)。

          5.1 工廠模式實(shí)戰(zhàn)

          5.1.1 支付渠道選中分析

          用戶每次下單完成后,需要支付訂單,支付訂單會(huì)根據(jù)自身情況選擇不同支付方式,后臺(tái)服務(wù)會(huì)根據(jù)用戶選中不同創(chuàng)建不同支付渠道的實(shí)例,這里創(chuàng)建支付渠道的實(shí)例可以采用工廠方法模式。

          5.1.2 代碼實(shí)現(xiàn)

          工廠方法在SpringBoot中如果在用工廠的同時(shí)又出現(xiàn)了new,那絕對(duì)是一個(gè)敗筆。在SpringBoot中,幾乎所有對(duì)象

          都可以直接交給Spring容器管理,它天然已經(jīng)是一個(gè)工廠對(duì)象,因此在SpringBoot項(xiàng)目中用工廠模式,再頻繁new對(duì)象反而不妥。那么工廠模式究竟怎么用在SpringBoot項(xiàng)目的支付場(chǎng)景呢?其實(shí)很簡(jiǎn)單,如果我們要選擇一個(gè)支付渠道,而項(xiàng)目中有100種支付渠道,那這個(gè)時(shí)候無(wú)疑要寫100個(gè) @Autowired 注入100個(gè)支付渠道,并且需要做100種判斷,這個(gè)時(shí)候我們可以用工廠模式取代我們判斷,直接根據(jù)我們配置的映射關(guān)系從Spring容器中拿到對(duì)應(yīng)支付渠道的實(shí)例,代碼量將大大減少,這塊是使用工廠的另一種妙用

          支付接口:?PayChannel 定義支付行為。

          微信支付實(shí)現(xiàn)WeixinPay 實(shí)現(xiàn)微信支付操作,這里只模擬。

          支付寶支付實(shí)現(xiàn):?AliPay 實(shí)現(xiàn)支付寶支付,這里只模擬。

          支付渠道映射配置在 application.yml 中配置支付渠道映射,每次從前端傳入支付ID即可從配置中獲取支付渠道對(duì)應(yīng)Spring容器中實(shí)例的id。

          支付渠道獲取工廠創(chuàng)建創(chuàng)建 PayFactory 用于獲取支付渠道的實(shí)例,我們這里通過(guò)映射的key獲取Spring容器中實(shí)例的id值,然后從Spring容器中根據(jù)id獲取對(duì)應(yīng)實(shí)例,因此該工廠需要實(shí)現(xiàn)接口 ApplicationContextAware 來(lái)獲取容器。

          支付渠道調(diào)用實(shí)現(xiàn)修改 PayServiceImpl 的 pay 方法,實(shí)現(xiàn)支付,代碼如下:

          測(cè)試當(dāng)我們選中支付渠道為1(微信支付)或者2(支付寶支付)的時(shí)候,都能爭(zhēng)取獲取對(duì)應(yīng)的渠道實(shí)例。

          6 狀態(tài)模式

          案例:訂單不同狀態(tài),執(zhí)行不同操作

          定義:對(duì)有狀態(tài)的對(duì)象,把復(fù)雜的“判斷邏輯”提取到不同的狀態(tài)對(duì)象中,允許狀態(tài)對(duì)象在其內(nèi)部狀態(tài)發(fā)生改變時(shí)改變其行為。

          優(yōu)點(diǎn)

          缺點(diǎn)

          6.1 狀態(tài)模式實(shí)戰(zhàn)

          6.1.1 狀態(tài)模式案例分析

          在電商案例中,訂單狀態(tài)每次發(fā)生變更,都要執(zhí)行不同的操作,這里正好可以使用狀態(tài)模式。當(dāng)訂單完成支付的時(shí)候,我們需要立即通知商家發(fā)貨,當(dāng)訂單執(zhí)行取消的時(shí)候,我們需要執(zhí)行庫(kù)存回滾,如果訂單已支付,還需要執(zhí)行退款操作,無(wú)論是通知商家發(fā)貨還是執(zhí)行庫(kù)存回滾,都是有訂單狀態(tài)決定,因此這里可以使用狀態(tài)模式來(lái)實(shí)現(xiàn)

          我們可以先定義狀態(tài)接口 State ,給狀態(tài)接口實(shí)現(xiàn)兩個(gè)不同的行為,分別是發(fā)貨和回滾庫(kù)存并退款,把該狀態(tài)對(duì)象添加到訂單內(nèi)部作為成員屬性,當(dāng)訂單的 state 狀態(tài)改變時(shí),觸發(fā)執(zhí)行不同的狀態(tài)行為動(dòng)作。

          5.1.2 案例實(shí)現(xiàn)

          狀態(tài)接口定義:State 接口,用于定義更新狀態(tài)對(duì)象,同時(shí)執(zhí)行相關(guān)的行為。

          發(fā)通知消息行為定義SendMsgBehavior 用于實(shí)現(xiàn)給商家發(fā)送消息通知發(fā)貨,這里模擬發(fā)送消息的行為。

          庫(kù)存回滾并退款創(chuàng)建 ResetStoreBehavior ,用于實(shí)現(xiàn)訂單庫(kù)存回滾,并給用戶退款操作,這里退款模擬相關(guān)行

          為。

          測(cè)試:

          支付訂單的時(shí)候,如果支付成功,我們調(diào)用 State 變更對(duì)應(yīng)的狀態(tài)行為,并執(zhí)行相關(guān)行為,代碼如下:

          測(cè)試結(jié)果如下:


          干貨分享

          最近將個(gè)人學(xué)習(xí)筆記整理成冊(cè),使用PDF分享。關(guān)注我,回復(fù)如下代碼,即可獲得百度盤地址,無(wú)套路領(lǐng)取!

          ?001:《Java并發(fā)與高并發(fā)解決方案》學(xué)習(xí)筆記;?002:《深入JVM內(nèi)核——原理、診斷與優(yōu)化》學(xué)習(xí)筆記;?003:《Java面試寶典》?004:《Docker開源書》?005:《Kubernetes開源書》?006:《DDD速成(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)速成)》?007:全部?008:加技術(shù)群討論

          加個(gè)關(guān)注不迷路


          喜歡就點(diǎn)個(gè)"在看"唄^_^

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青爱人人射 | 欧熟视频 | 69视频在线观看 | 大香蕉插插插 | 人妻日日爽夜夜爽一区二区 |