需求
最近寫(xiě)了一個(gè)服務(wù):根據(jù)優(yōu)惠券的類(lèi)型resourceType和編碼resourceId來(lái) 查詢(xún) 發(fā)放方式grantType和領(lǐng)取規(guī)則
實(shí)現(xiàn)方式:
根據(jù)優(yōu)惠券類(lèi)型resourceType -> 確定查詢(xún)哪個(gè)數(shù)據(jù)表
根據(jù)編碼resourceId -> 到對(duì)應(yīng)的數(shù)據(jù)表里邊查詢(xún)優(yōu)惠券的派發(fā)方式grantType和領(lǐng)取規(guī)則
優(yōu)惠券有多種類(lèi)型,分別對(duì)應(yīng)了不同的數(shù)據(jù)庫(kù)表:
紅包 —— 紅包發(fā)放規(guī)則表
購(gòu)物券 —— 購(gòu)物券表
QQ會(huì)員
外賣(mài)會(huì)員
實(shí)際的優(yōu)惠券遠(yuǎn)不止這些,這個(gè)需求是要我們寫(xiě)一個(gè)業(yè)務(wù)分派的邏輯
第一個(gè)能想到的思路就是if-else或者switch case:
switch(resourceType){ case"紅包": 查詢(xún)紅包的派發(fā)方式 break; case"購(gòu)物券": 查詢(xún)購(gòu)物券的派發(fā)方式 break; case"QQ會(huì)員": break; case"外賣(mài)會(huì)員": break; ...... default:logger.info("查找不到該優(yōu)惠券類(lèi)型resourceType以及對(duì)應(yīng)的派發(fā)方式"); break; }
如果要這么寫(xiě)的話, 一個(gè)方法的代碼可就太長(zhǎng)了,影響了可讀性。(別看著上面case里面只有一句話,但實(shí)際情況是有很多行的)
而且由于 整個(gè) if-else的代碼有很多行,也不方便修改,可維護(hù)性低。
策略模式
策略模式是把 if語(yǔ)句里面的邏輯抽出來(lái)寫(xiě)成一個(gè)類(lèi),如果要修改某個(gè)邏輯的話,僅修改一個(gè)具體的實(shí)現(xiàn)類(lèi)的邏輯即可,可維護(hù)性會(huì)好不少。
以下是策略模式的具體結(jié)構(gòu)
策略模式在業(yè)務(wù)邏輯分派的時(shí)候還是if-else,只是說(shuō)比第一種思路的if-else 更好維護(hù)一點(diǎn)。
switch(resourceType){ case"紅包": StringgrantType=newContext(newRedPaper()).ContextInterface(); break; case"購(gòu)物券": StringgrantType=newContext(newShopping()).ContextInterface(); break; ...... default:logger.info("查找不到該優(yōu)惠券類(lèi)型resourceType以及對(duì)應(yīng)的派發(fā)方式"); break;
但缺點(diǎn)也明顯:
如果 if-else的判斷情況很多,那么對(duì)應(yīng)的具體策略實(shí)現(xiàn)類(lèi)也會(huì)很多,上邊的具體的策略實(shí)現(xiàn)類(lèi)還只是2個(gè),查詢(xún)紅包發(fā)放方式寫(xiě)在類(lèi)RedPaper里邊,購(gòu)物券寫(xiě)在另一個(gè)類(lèi)Shopping里邊;那資源類(lèi)型多個(gè)QQ會(huì)員和外賣(mài)會(huì)員,不就得再多寫(xiě)兩個(gè)類(lèi)?有點(diǎn)麻煩了
沒(méi)法俯視整個(gè)分派的業(yè)務(wù)邏輯
Map+函數(shù)式接口
用上了Java8的新特性lambda表達(dá)式
判斷條件放在key中
對(duì)應(yīng)的業(yè)務(wù)邏輯放在value中
這樣子寫(xiě)的好處是非常直觀,能直接看到判斷條件對(duì)應(yīng)的業(yè)務(wù)邏輯
需求:根據(jù)優(yōu)惠券(資源)類(lèi)型resourceType和編碼resourceId查詢(xún)派發(fā)方式grantType
上代碼:
@Service publicclassQueryGrantTypeService{ @Autowired privateGrantTypeSerivegrantTypeSerive; privateMap>grantTypeMap=newHashMap<>(); /** *初始化業(yè)務(wù)分派邏輯,代替了if-else部分 *key:優(yōu)惠券類(lèi)型 *value:lambda表達(dá)式,最終會(huì)獲得該優(yōu)惠券的發(fā)放方式 */ @PostConstruct publicvoiddispatcherInit(){ grantTypeMap.put("紅包",resourceId->grantTypeSerive.redPaper(resourceId)); grantTypeMap.put("購(gòu)物券",resourceId->grantTypeSerive.shopping(resourceId)); grantTypeMap.put("qq會(huì)員",resourceId->grantTypeSerive.QQVip(resourceId)); } publicStringgetResult(StringresourceType){ //Controller根據(jù)優(yōu)惠券類(lèi)型resourceType、編碼resourceId去查詢(xún)發(fā)放方式grantType Function result=getGrantTypeMap.get(resourceType); if(result!=null){ //傳入resourceId執(zhí)行這段表達(dá)式獲得String型的grantType returnresult.apply(resourceId); } return"查詢(xún)不到該優(yōu)惠券的發(fā)放方式"; } }
如果單個(gè) if 語(yǔ)句塊的業(yè)務(wù)邏輯有很多行的話,我們可以把這些 業(yè)務(wù)操作抽出來(lái),寫(xiě)成一個(gè)單獨(dú)的Service,即:
//具體的邏輯操作 @Service publicclassGrantTypeSerive{ publicStringredPaper(StringresourceId){ //紅包的發(fā)放方式 return"每周末9點(diǎn)發(fā)放"; } publicStringshopping(StringresourceId){ //購(gòu)物券的發(fā)放方式 return"每周三9點(diǎn)發(fā)放"; } publicStringQQVip(StringresourceId){ //qq會(huì)員的發(fā)放方式 return"每周一0點(diǎn)開(kāi)始秒殺"; } }
入?yún)tring resourceId是用來(lái)查數(shù)據(jù)庫(kù)的,這里簡(jiǎn)化了,傳參之后不做處理。
用http調(diào)用的結(jié)果:
@RestController publicclassGrantTypeController{ @Autowired privateQueryGrantTypeServicequeryGrantTypeService; @PostMapping("/grantType") publicStringtest(StringresourceName){ returnqueryGrantTypeService.getResult(resourceName); } }
用Map+函數(shù)式接口也有弊端:
你的隊(duì)友得會(huì)lambda表達(dá)式才行啊,他不會(huì)讓他自己百度去
最后捋一捋本文講了什么
策略模式通過(guò)接口、實(shí)現(xiàn)類(lèi)、邏輯分派來(lái)完成,把 if語(yǔ)句塊的邏輯抽出來(lái)寫(xiě)成一個(gè)類(lèi),更好維護(hù)。
Map+函數(shù)式接口通過(guò)Map.get(key)來(lái)代替 if-else的業(yè)務(wù)分派,能夠避免策略模式帶來(lái)的類(lèi)增多、難以俯視整個(gè)業(yè)務(wù)邏輯的問(wèn)題。
審核編輯:劉清
-
編碼器
+關(guān)注
關(guān)注
45文章
3639瀏覽量
134437 -
數(shù)據(jù)庫(kù)
+關(guān)注
關(guān)注
7文章
3795瀏覽量
64364
原文標(biāo)題:Map+函數(shù)式接口,“更完美” 的解決 if-else的問(wèn)題
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論