if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!
△Hollis, 一個(gè)對(duì)Coding有著獨(dú)特追求的人△
這是Hollis的第?259篇原創(chuàng)分享
作者 l 南山獅
來(lái)源 l Hollis(ID:hollischuang)
我也不用設(shè)計(jì)模式
很多人覺(jué)得自己寫(xiě)的是業(yè)務(wù)代碼,按照邏輯寫(xiě)下去,再把公用的方法抽出來(lái)復(fù)用就可以了,設(shè)計(jì)模式根本就沒(méi)必要用,更沒(méi)必要學(xué)。
一開(kāi)始的時(shí)候,我也是這么想,直到我遇到。。。
舉個(gè)栗子
我們先看一個(gè)普通的下單攔截接口。
基本邏輯,參數(shù)安全攔截,次數(shù)攔截,規(guī)則攔截,都通過(guò),返回允許下單,任意一個(gè)失敗,返回對(duì)應(yīng)的失敗原因。
多層嵌套if寫(xiě)法
我們正常多層嵌套if的寫(xiě)法
/***?@author?saier*?@date?2020/3/31?18:03*/ public?class?Order?{public?Message?interrupt1(){return?null;}public?Message?interrupt2(){return?null;}public?Message?interrupt3(){return?null;}public?Message?interrupt4(){return?null;}public?Message?interrupt5(){return?null;}public?static?void?main(String[]?args)?{Order?order=?new?Order();if(order.interrupt1().getResult()?==?1){if(order.interrupt2().getResult()?==?1){if(order.interrupt3().getResult()?==?1){if(order.interrupt4().getResult()?==?1){if(order.interrupt5().getResult()?==?1){System.out.println("success");}}}}}} }@Data class?Message?{private?int?result;private?String?msg; }異常處理邏輯
或者有些利用異常做邏輯,代碼會(huì)簡(jiǎn)單一點(diǎn)
/***?@author?saier*?@date?2020/3/31?18:03*/ public?class?Order2?{public?void?interrupt1(){}public?void?interrupt2(){}public?void?interrupt3(){//失敗throw?new?RuntimeException();}public?void?interrupt4(){//失敗throw?new?RuntimeException();}public?void?interrupt5(){//失敗throw?new?RuntimeException();}public?static?void?main(String[]?args)?{Order2?order2=?new?Order2();try{order2.interrupt1();order2.interrupt2();order2.interrupt3();order2.interrupt4();order2.interrupt5();System.out.println("success");}catch?(RuntimeException?e){System.out.println("fail");}} }一開(kāi)始,我就直接使用異常來(lái)做邏輯。但后續(xù)邏輯越來(lái)越復(fù)雜之后,也會(huì)出現(xiàn)一些問(wèn)題。例如異常只能返回異常信息,不能返回更多的字段信息。
后面也留意到,異常做邏輯,在阿里規(guī)范是禁止的。
阿里代碼規(guī)范 :
【強(qiáng)制】異常不要用來(lái)做流程控制,條件控制。
說(shuō)明:異常設(shè)計(jì)的初衷是解決程序運(yùn)行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多。
更重要的是,代碼可讀性太差了,隨時(shí)一個(gè)方法的異常拋出來(lái),還要考慮代碼本身的異常。
沒(méi)更好的辦法,只能考慮設(shè)計(jì)模式了
怎么改,會(huì)使代碼的可讀性高,擴(kuò)展性好?
在同事的提醒下,突然想起了設(shè)計(jì)模式!
我們希望達(dá)到的目的
代碼沒(méi)有這么多if else嵌套,可讀性高
如果新增新的攔截邏輯簡(jiǎn)單方便,不影響原本的邏輯,擴(kuò)展性好
可以很方便地調(diào)換攔截邏輯順序,低耦合
責(zé)任鏈模式
在這種場(chǎng)景下,非常適合責(zé)任鏈模式。(什么場(chǎng)景使用什么設(shè)計(jì)模式,這就需要平時(shí)有積累,知道各種設(shè)計(jì)模式的基本使用)
責(zé)任鏈,顧名思義,就是用來(lái)處理相關(guān)事務(wù)責(zé)任的一條執(zhí)行鏈,執(zhí)行鏈上有多個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都有機(jī)會(huì)(條件匹配)處理請(qǐng)求事務(wù),如果某個(gè)節(jié)點(diǎn)處理完了就可以根據(jù)實(shí)際業(yè)務(wù)需求傳遞給下一個(gè)節(jié)點(diǎn)繼續(xù)處理或者返回處理完畢。
首先,建立過(guò)濾器的抽象類(lèi)
public?abstract?class?AbstractFilter?{private?AbstractFilter?nextFilter;/***?責(zé)任鏈的下一個(gè)元素*/public?void?setNextFilter(AbstractFilter?nextFilter){this.nextFilter?=?nextFilter;}public?AbstractFilter?getLastFilter(){if(this.nextFilter?!=?null){return?this.nextFilter.getLastFilter();}else{return?this;}}public?void?filter(FilterRequest?filterRequest,?Response?response){doFilter(filterRequest,response);if(response.isFilterNext()?&&?nextFilter?!=?null){nextFilter.filter(filterRequest,response);}}/***?具體攔截邏輯*/public?abstract?void?doFilter(FilterRequest?filterRequest,?Response?response);/***?根據(jù)攔截結(jié)果做處理*/public?void?exec(FilterRequest?filterRequest,?Response?response){} }過(guò)濾器的實(shí)現(xiàn)類(lèi)
@Component @Order(5) public?class?CheckParamFilter1?extends?AbstractFilter?{@Overridepublic?void?doFilter(FilterRequest?filterRequest,?Response?response)?{} }@Component @Order(10) public?class?CheckParamFilter2?extends?AbstractFilter?{@Overridepublic?void?doFilter(FilterRequest?filterRequest,?Response?response)?{} }使用Order注解,確定過(guò)濾器的順序,后續(xù)在spring注入的時(shí)候,會(huì)有奇效
//利用spring的自動(dòng)注入機(jī)制 @Autowired List<AbstractFilter>?abstractFilterList;private?AbstractFilter?firstFilter;//spring注入后自動(dòng)執(zhí)行 @PostConstruct public?void?initializeChainFilter(){//把所有調(diào)用的邏輯注入到責(zé)任鏈,按照Order排序,越小優(yōu)先級(jí)越高for(int?i?=?0;i<abstractFilterList.size();i++){if(i?==?0){firstFilter?=?abstractFilterList.get(i);}else{firstFilter.getLastFilter().setNextFilter(abstractFilterList.get(i));}} }//直接使用 public?Response?exec(){firstFilter.filter(filterRequest,?response);return?response; }使用設(shè)計(jì)模式的好處
看下使用責(zé)任鏈模式后,有什么好處!
新增攔截邏輯,只需要再實(shí)現(xiàn)一個(gè)AbstractFilter類(lèi)即可
修改攔截順序,只需要修改Order注解的大小,越小,優(yōu)先級(jí)越高
代碼清晰,所有處理邏輯下沉到實(shí)現(xiàn)類(lèi)中
使用設(shè)計(jì)模式的缺點(diǎn)
做到了低耦合,高擴(kuò)展。但也帶來(lái)了一些不好的地方
邏輯更復(fù)雜,用了鏈?zhǔn)降葦?shù)據(jù)結(jié)構(gòu),要注意單例的問(wèn)題,不能重復(fù)使用
類(lèi)數(shù)量激增,一個(gè)攔截器就一個(gè)類(lèi)
最后小結(jié)一下
不是什么地方都適合使用設(shè)計(jì)模式,如果邏輯簡(jiǎn)單,你硬要使用設(shè)計(jì)模式,只會(huì)帶來(lái)結(jié)構(gòu)上的復(fù)雜,大家可以按照大家的業(yè)務(wù)場(chǎng)景來(lái)使用。
關(guān)于作者:南山獅:理工男,7年互聯(lián)網(wǎng)電商系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn),知識(shí)分享領(lǐng)域探索小白。公眾號(hào):互聯(lián)網(wǎng)編程,白話文幫助你了解編程。
Java工程師成神之路系列文章在 GitHub 更新中,歡迎關(guān)注,歡迎star。?直面Java第305期:TLAB帶來(lái)的問(wèn)題?深入并發(fā)第013期:拓展synchronized——鎖優(yōu)化 - MORE | 更多精彩文章 -前端大神的離逝,讓我們不得不有所反思。 我,程序員,32歲,距離退休,只剩3年了! 99%的程序員都在用Lombok,原理竟然這么簡(jiǎn)單?我也手?jǐn)]了一個(gè)! 一個(gè)Java多線程的問(wèn)題,顛覆了我多年的認(rèn)知! 如果你喜歡本文,請(qǐng)長(zhǎng)按二維碼,關(guān)注?Hollis.轉(zhuǎn)發(fā)至朋友圈,是對(duì)我最大的支持。好文章,我在看??總結(jié)
以上是生活随笔為你收集整理的if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CodeForce 534C Polyc
- 下一篇: 2W 字详解设计模式!