if-else嵌套太深?教你一個新手都能掌握的設計模式搞定惩歉!

作者 l 南山獅
來源 l Hollis(ID:hollischuang)

我也不用設計模式

很多人覺得自己寫的是業(yè)務代碼等脂,按照邏輯寫下去,再把公用的方法抽出來復用就可以了撑蚌,設計模式根本就沒必要用上遥,更沒必要學。

一開始的時候争涌,我也是這么想粉楚,直到我遇到。亮垫。模软。

舉個栗子

我們先看一個普通的下單攔截接口。

基本邏輯饮潦,參數(shù)安全攔截燃异,次數(shù)攔截,規(guī)則攔截继蜡,都通過回俐,返回允許下單,任意一個失敗稀并,返回對應的失敗原因仅颇。

多層嵌套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");
        }

    }
}

一開始碘举,我就直接使用異常來做邏輯忘瓦。但后續(xù)邏輯越來越復雜之后,也會出現(xiàn)一些問題引颈。例如異常只能返回異常信息耕皮,不能返回更多的字段信息境蜕。

后面也留意到,異常做邏輯凌停,在阿里規(guī)范是禁止的汽摹。

阿里代碼規(guī)范 :
【強制】異常不要用來做流程控制,條件控制苦锨。
說明:異常設計的初衷是解決程序運行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多趴泌。
更重要的是舟舒,代碼可讀性太差了,隨時一個方法的異常拋出來嗜憔,還要考慮代碼本身的異常秃励。

沒更好的辦法,只能考慮設計模式了

怎么改吉捶,會使代碼的可讀性高夺鲜,擴展性好?

在同事的提醒下呐舔,突然想起了設計模式币励!

我們希望達到的目的

代碼沒有這么多if else嵌套,可讀性高
如果新增新的攔截邏輯簡單方便珊拼,不影響原本的邏輯食呻,擴展性好
可以很方便地調換攔截邏輯順序,低耦合
責任鏈模式

在這種場景下澎现,非常適合責任鏈模式仅胞。(什么場景使用什么設計模式,這就需要平時有積累剑辫,知道各種設計模式的基本使用)

責任鏈干旧,顧名思義,就是用來處理相關事務責任的一條執(zhí)行鏈妹蔽,執(zhí)行鏈上有多個節(jié)點椎眯,每個節(jié)點都有機會(條件匹配)處理請求事務,如果某個節(jié)點處理完了就可以根據(jù)實際業(yè)務需求傳遞給下一個節(jié)點繼續(xù)處理或者返回處理完畢讹开。
首先盅视,建立過濾器的抽象類

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);

    /**
     * 根據(jù)攔截結果做處理
     */
    public void exec(FilterRequest filterRequest, Response response){
    }
}

過濾器的實現(xiàn)類

@Component
@Order(5)
public class CheckParamFilter1 extends AbstractFilter {
    @Override
    public void doFilter(FilterRequest filterRequest, Response response) {

    }
}

@Component
@Order(10)
public class CheckParamFilter2 extends AbstractFilter {
    @Override
    public void doFilter(FilterRequest filterRequest, Response response) {

    }
}

使用Order注解,確定過濾器的順序旦万,后續(xù)在spring注入的時候闹击,會有奇效

//利用spring的自動注入機制
@Autowired
List<AbstractFilter> abstractFilterList;

private AbstractFilter firstFilter;

//spring注入后自動執(zhí)行
@PostConstruct
public void initializeChainFilter(){
    //把所有調用的邏輯注入到責任鏈,按照Order排序成艘,越小優(yōu)先級越高
    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;
}

使用設計模式的好處

看下使用責任鏈模式后赏半,有什么好處贺归!

新增攔截邏輯,只需要再實現(xiàn)一個AbstractFilter類即可
修改攔截順序断箫,只需要修改Order注解的大小拂酣,越小,優(yōu)先級越高
代碼清晰仲义,所有處理邏輯下沉到實現(xiàn)類中
使用設計模式的缺點

做到了低耦合婶熬,高擴展。但也帶來了一些不好的地方

邏輯更復雜埃撵,用了鏈式等數(shù)據(jù)結構赵颅,要注意單例的問題,不能重復使用
類數(shù)量激增暂刘,一個攔截器就一個類
最后小結一下

不是什么地方都適合使用設計模式饺谬,如果邏輯簡單,你硬要使用設計模式谣拣,只會帶來結構上的復雜募寨,大家可以按照大家的業(yè)務場景來使用。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末森缠,一起剝皮案震驚了整個濱河市拔鹰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贵涵,老刑警劉巖格郁,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異独悴,居然都是意外死亡例书,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門刻炒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來决采,“玉大人,你說我怎么就攤上這事坟奥∈鞑t!?“怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵爱谁,是天一觀的道長晒喷。 經(jīng)常有香客問我,道長访敌,這世上最難降的妖魔是什么凉敲? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上爷抓,老公的妹妹穿的比我還像新娘势决。我一直安慰自己,他們只是感情好蓝撇,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布果复。 她就那樣靜靜地躺著,像睡著了一般渤昌。 火紅的嫁衣襯著肌膚如雪虽抄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天独柑,我揣著相機與錄音极颓,去河邊找鬼。 笑死群嗤,一個胖子當著我的面吹牛,可吹牛的內容都是我干的兵琳。 我是一名探鬼主播狂秘,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼躯肌!你這毒婦竟也來了者春?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤清女,失蹤者是張志新(化名)和其女友劉穎钱烟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嫡丙,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拴袭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了曙博。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拥刻。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖父泳,靈堂內的尸體忽然破棺而出般哼,到底是詐尸還是另有隱情,我是刑警寧澤惠窄,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布蒸眠,位于F島的核電站,受9級特大地震影響杆融,放射性物質發(fā)生泄漏楞卡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臀晃。 院中可真熱鬧觉渴,春花似錦、人聲如沸徽惋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽险绘。三九已至踢京,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宦棺,已是汗流浹背瓣距。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留代咸,地道東北人蹈丸。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像呐芥,于是被迫代替她去往敵國和親逻杖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內容