自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Go設(shè)計(jì)模式實(shí)戰(zhàn)--用職責(zé)鏈實(shí)現(xiàn)購(gòu)物車與商品優(yōu)惠的解耦

開(kāi)發(fā) 前端
我們來(lái)實(shí)現(xiàn)couponChecker、discountChecker、vipChecker 三個(gè)具體的流程步驟的處理類,他們各自要處理的邏輯都封裝在自己實(shí)現(xiàn)的Check方法中。


上一節(jié)「Go項(xiàng)目實(shí)戰(zhàn)-購(gòu)物車功能的核心接口開(kāi)發(fā)」中我們完成了購(gòu)物車模塊的基本功能的開(kāi)發(fā),所有購(gòu)物車功能中存在變數(shù)的就是購(gòu)物車的賬單結(jié)算功能,也是未來(lái)經(jīng)常可能會(huì)遇到需求改動(dòng)的功能?各種促銷活動(dòng)相關(guān)的需求都會(huì)要求涵蓋在這個(gè)功能中。

我們理解的購(gòu)物車結(jié)算功能,一開(kāi)始可能是是下面這個(gè)清純版的

圖片圖片

但實(shí)際上公司產(chǎn)品要求的購(gòu)物車結(jié)算功能是下面這張圖這樣,不光能算出商品總價(jià),還要能綜合考慮用戶是不是VIP,有沒(méi)有優(yōu)惠券、夠不夠參加滿減活動(dòng)。

圖片圖片

而且促銷活動(dòng)的玩法可能遠(yuǎn)不止這么多未來(lái)還有可能增加新的玩法。每次新增一個(gè)玩法我們的結(jié)算模塊代碼大概率又需要增加一個(gè)代碼分支,做相應(yīng)的查詢和判斷等等操作來(lái)滿足新的促銷玩法。

那么有沒(méi)有什么設(shè)計(jì)模式能讓我們稍微緩解一下代碼不停添加條件分支來(lái)適應(yīng)新需求呢?我這么說(shuō)了,當(dāng)然是有了,這就是職責(zé)鏈模式,也有的資料叫責(zé)任鏈模式。本節(jié)我們把購(gòu)物車的賬單結(jié)算功能使用職責(zé)鏈進(jìn)行改造,讓它支持優(yōu)惠券、滿減活動(dòng)、VIP折扣能促銷功能的應(yīng)用。

不過(guò)首先我們需要聊一下什么是責(zé)任鏈模式。

職責(zé)鏈模式

職責(zé)鏈在很多流行框架里都有被用到,像中間件、攔截器等框架組件都是應(yīng)用的這種設(shè)計(jì)模式,這兩個(gè)組價(jià)大家應(yīng)該用的比較多。但其實(shí)在一些核心的業(yè)務(wù)中,應(yīng)用職責(zé)鏈模式也能夠讓我們“相對(duì)無(wú)痛地”擴(kuò)展業(yè)務(wù)流程的步驟。

注意我上面的用詞“相對(duì)無(wú)痛”,意思是我們不用不停地在原有步驟中增加if else 判斷,不必修改原有已經(jīng)開(kāi)發(fā)好,經(jīng)過(guò)測(cè)試的流程。但還是有些代碼開(kāi)發(fā)成本的,也會(huì)增加代碼的復(fù)雜度,真正做到“無(wú)痛”,那你的轉(zhuǎn)個(gè)行當(dāng)甲方,最好是當(dāng)老板才行。。。

職責(zé)鏈的實(shí)現(xiàn)步驟分析

我們通過(guò)上面流程擴(kuò)展的痛點(diǎn)可以想到,流程中每個(gè)步驟都應(yīng)由一個(gè)處理對(duì)象來(lái)完成邏輯抽象、所有處理對(duì)象都應(yīng)該提供統(tǒng)一的處理自身邏輯的方法,其次還應(yīng)該維護(hù)指向下一個(gè)處理對(duì)象的引用,當(dāng)前步驟自己邏輯處理完后,就調(diào)用下一個(gè)對(duì)象的處理方法,把請(qǐng)求交給后面的對(duì)象進(jìn)行處理,依次遞進(jìn)直到流程結(jié)束。

如果抽象成 UML 類圖表示的話,差不多就是下面這個(gè)樣子。

圖片圖片

圖片圖片

了解完職責(zé)鏈模式從接口和類型設(shè)計(jì)上應(yīng)該怎么實(shí)現(xiàn)后,我們進(jìn)入代碼實(shí)現(xiàn)環(huán)節(jié)。

用職責(zé)鏈模式改造購(gòu)物車結(jié)算功能

以我們項(xiàng)目的購(gòu)物車結(jié)算功能在加入促銷相關(guān)的需求后,其流程如下:

查購(gòu)物信息--> 查看的可用優(yōu)惠券--> 查滿減活動(dòng)-->查VIP資格和折扣-->生成賬單信息。

開(kāi)頭和結(jié)尾的步驟固定,不管什么類型的用戶都會(huì)有這個(gè)流程,中間的促銷流程則是變數(shù),我們的目標(biāo)是利用職責(zé)鏈模式,實(shí)現(xiàn)這個(gè)流程中的每個(gè)步驟,且相互間不耦合,還支持向流程中增加步驟。

改造結(jié)算功能的第一步,是先確定新的結(jié)算功能返回的響應(yīng),我們把購(gòu)物車功能結(jié)算的響應(yīng)對(duì)象改造為以下結(jié)構(gòu),增加了促銷相關(guān)的信息,這樣客戶端拿到后也能展示給用戶,讓用戶知道自己用了哪些優(yōu)惠。

新的購(gòu)物車結(jié)算功能的響應(yīng)對(duì)象如下。

type CheckedCartItemBillV2 struct {
 Items      []*CartItem `json:"items"`
 BillDetail struct {
  Coupon struct { // 可用的優(yōu)惠券
   CouponId      int64`json:"coupon_id"`
   CouponName    string`json:"coupon_name"`
   DiscountMoney int    `json:"discount_money"`
  } `json:"coupon"`
  Discount struct { // 可用的滿減活動(dòng)券
   DiscountId    int64`json:"discount_id"`
   DiscountName  string`json:"discount_name"`
   DiscountMoney int    `json:"discount_money"`
  } `json:"discount"`
  VipDiscountMoney   int`json:"vip_discount_money"`   // VIP減免的金額
  OriginalTotalPrice int`json:"original_total_price"`// 減免、優(yōu)惠前的總金額
  TotalPrice         int`json:"total_price"`          // 實(shí)際要支付的總金額
 } `json:"bill_detail"`
}

我們服務(wù)層使用的領(lǐng)域?qū)ο笠残枰稣{(diào)整。

type CartBillInfo struct {
 Coupon struct { // 可用的優(yōu)惠券
  CouponId      int64
  CouponName    string
  DiscountMoney int
  Threshold     int// 使用門檻, 比如滿1000 可用

 }
 Discount struct { // 可用的滿減活動(dòng)券
  DiscountId    int64
  DiscountName  string
  DiscountMoney int
  Threshold     int// 使用門檻, 比如滿1000 可用
 }
 VipDiscountMoney   int// VIP減免的金額
 OriginalTotalPrice int// 減免、優(yōu)惠前的總金額
 TotalPrice         int// 實(shí)際要支付的總金額
}

接下來(lái)我們先來(lái)實(shí)現(xiàn)職責(zé)鏈模式里的公共部分—即模式的接口和抽象類,在logic/domainservice中新建cart_bill_checker.go 新增以下Interface。

type cartBillCheckHandler interface {
 RunChecker(*CartBillChecker) error
 SetNext(cartBillCheckHandler) cartBillCheckHandler
 Check(*CartBillChecker) error
}

接下來(lái)定義 cartCommonChecker ,它充當(dāng)抽象類型,實(shí)現(xiàn)公共方法。

type cartCommonChecker struct {
 nextHandler cartBillCheckHandler
}

func (n *cartCommonChecker) SetNext(handler cartBillCheckHandler) cartBillCheckHandler {
 n.nextHandler = handler
return handler
}

func (n *cartCommonChecker) RunChecker(billChecker *CartBillChecker) (err error) {
if n.nextHandler != nil {
if err = n.nextHandler.Check(billChecker); err != nil {
   err = errcode.Wrap("CartBillCheckerError", err)
   return
  }

return n.nextHandler.RunChecker(billChecker)
 }

return
}

抽象方法 Check 則留給像下面優(yōu)惠券處理類 couponChecker 這樣的匿名嵌套了 cartCommonChecker 的具體處理類去實(shí)現(xiàn)。

我們來(lái)實(shí)現(xiàn)couponChecker、discountChecker、vipChecker 三個(gè)具體的流程步驟的處理類,他們各自要處理的邏輯都封裝在自己實(shí)現(xiàn)的Check方法中。

責(zé)任編輯:武曉燕 來(lái)源: 網(wǎng)管叨bi叨
相關(guān)推薦

2024-12-02 08:30:19

2025-03-10 09:07:20

2022-12-16 08:52:14

購(gòu)物車系統(tǒng)存儲(chǔ)

2009-07-07 15:57:29

JSP購(gòu)物車

2015-08-03 11:48:12

購(gòu)物車動(dòng)畫

2022-06-28 14:42:26

ETS購(gòu)物車應(yīng)用

2011-04-14 10:08:04

AJAXPHPJQuery

2024-12-05 09:13:55

Go項(xiàng)目模塊

2023-01-09 08:43:53

Go設(shè)計(jì)模式

2021-02-01 09:57:29

鴻蒙HarmonyOS應(yīng)用

2018-05-28 09:53:12

京東購(gòu)物車Java

2023-03-03 08:12:07

設(shè)計(jì)模式語(yǔ)言

2020-10-16 18:41:43

command設(shè)計(jì)模式代碼

2021-01-07 10:30:23

設(shè)計(jì)模式

2022-09-02 08:23:12

軟件開(kāi)發(fā)解耦架構(gòu)

2025-03-17 07:47:29

Spring分布式緩存

2023-11-08 08:01:40

Spring購(gòu)物車代碼

2012-10-08 11:18:05

JavaMVC項(xiàng)目

2022-09-13 16:01:13

購(gòu)物車京東接口

2009-07-28 13:47:47

ASP.NET電子商務(wù)ASP.NET購(gòu)物車
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)