if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!
△Hollis, 一個對Coding有著獨特追求的人△
這是Hollis的第?259篇原創分享
作者 l 南山獅
來源 l Hollis(ID:hollischuang)
我也不用設計模式
很多人覺得自己寫的是業務代碼,按照邏輯寫下去,再把公用的方法抽出來復用就可以了,設計模式根本就沒必要用,更沒必要學。
一開始的時候,我也是這么想,直到我遇到。。。
舉個栗子
我們先看一個普通的下單攔截接口。
基本邏輯,參數安全攔截,次數攔截,規則攔截,都通過,返回允許下單,任意一個失敗,返回對應的失敗原因。
多層嵌套if寫法
我們正常多層嵌套if的寫法
/***?@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; }異常處理邏輯
或者有些利用異常做邏輯,代碼會簡單一點
/***?@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");}} }一開始,我就直接使用異常來做邏輯。但后續邏輯越來越復雜之后,也會出現一些問題。例如異常只能返回異常信息,不能返回更多的字段信息。
后面也留意到,異常做邏輯,在阿里規范是禁止的。
阿里代碼規范 :
【強制】異常不要用來做流程控制,條件控制。
說明:異常設計的初衷是解決程序運行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多。
更重要的是,代碼可讀性太差了,隨時一個方法的異常拋出來,還要考慮代碼本身的異常。
沒更好的辦法,只能考慮設計模式了
怎么改,會使代碼的可讀性高,擴展性好?
在同事的提醒下,突然想起了設計模式!
我們希望達到的目的
代碼沒有這么多if else嵌套,可讀性高
如果新增新的攔截邏輯簡單方便,不影響原本的邏輯,擴展性好
可以很方便地調換攔截邏輯順序,低耦合
責任鏈模式
在這種場景下,非常適合責任鏈模式。(什么場景使用什么設計模式,這就需要平時有積累,知道各種設計模式的基本使用)
責任鏈,顧名思義,就是用來處理相關事務責任的一條執行鏈,執行鏈上有多個節點,每個節點都有機會(條件匹配)處理請求事務,如果某個節點處理完了就可以根據實際業務需求傳遞給下一個節點繼續處理或者返回處理完畢。
首先,建立過濾器的抽象類
public?abstract?class?AbstractFilter?{private?AbstractFilter?nextFilter;/***?責任鏈的下一個元素*/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);/***?根據攔截結果做處理*/public?void?exec(FilterRequest?filterRequest,?Response?response){} }過濾器的實現類
@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注解,確定過濾器的順序,后續在spring注入的時候,會有奇效
//利用spring的自動注入機制 @Autowired List<AbstractFilter>?abstractFilterList;private?AbstractFilter?firstFilter;//spring注入后自動執行 @PostConstruct public?void?initializeChainFilter(){//把所有調用的邏輯注入到責任鏈,按照Order排序,越小優先級越高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; }使用設計模式的好處
看下使用責任鏈模式后,有什么好處!
新增攔截邏輯,只需要再實現一個AbstractFilter類即可
修改攔截順序,只需要修改Order注解的大小,越小,優先級越高
代碼清晰,所有處理邏輯下沉到實現類中
使用設計模式的缺點
做到了低耦合,高擴展。但也帶來了一些不好的地方
邏輯更復雜,用了鏈式等數據結構,要注意單例的問題,不能重復使用
類數量激增,一個攔截器就一個類
最后小結一下
不是什么地方都適合使用設計模式,如果邏輯簡單,你硬要使用設計模式,只會帶來結構上的復雜,大家可以按照大家的業務場景來使用。
關于作者:南山獅:理工男,7年互聯網電商系統開發經驗,知識分享領域探索小白。公眾號:互聯網編程,白話文幫助你了解編程。
Java工程師成神之路系列文章在 GitHub 更新中,歡迎關注,歡迎star。?直面Java第305期:TLAB帶來的問題?深入并發第013期:拓展synchronized——鎖優化 - MORE | 更多精彩文章 -前端大神的離逝,讓我們不得不有所反思。 我,程序員,32歲,距離退休,只剩3年了! 99%的程序員都在用Lombok,原理竟然這么簡單?我也手擼了一個! 一個Java多線程的問題,顛覆了我多年的認知! 如果你喜歡本文,請長按二維碼,關注?Hollis.轉發至朋友圈,是對我最大的支持。好文章,我在看??總結
以上是生活随笔為你收集整理的if-else嵌套太深?教你一个新手都能掌握的设计模式搞定!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForce 534C Polyc
- 下一篇: 2015年年度总结