欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

優(yōu)化Java代碼中if-else的方案分享

 更新時(shí)間:2023年05月31日 11:40:42   作者:京東云開發(fā)者  
代碼可讀性是衡量代碼質(zhì)量的重要標(biāo)準(zhǔn),可讀性也是可維護(hù)性、可擴(kuò)展性的保證,而我們在編程時(shí)常常會發(fā)現(xiàn)代碼中有大量if?else語句,如何進(jìn)行優(yōu)化呢,下面就來和大家詳細(xì)聊聊

0.問題概述

代碼可讀性是衡量代碼質(zhì)量的重要標(biāo)準(zhǔn),可讀性也是可維護(hù)性、可擴(kuò)展性的保證,因?yàn)榇a是連接程序員和機(jī)器的中間橋梁,要對雙邊友好。Quora 上有一個(gè)帖子: “What are some of the most basic things every programmer should know?”

其中:

  • Code that’s hard to understand is hard to maintain.
  • Code that’s hard to maintain is next to useless.

也強(qiáng)調(diào)了"easy understand"代碼的重要性。

寫這篇文章的契機(jī)是在研讀Apache ShenYu項(xiàng)目時(shí),看到了很大一坨的if else語句,如下:

這里并非評論這段代碼寫法有問題,因?yàn)槲疫€并沒有深入到項(xiàng)目細(xì)節(jié)之中,可能這已經(jīng)是多輪優(yōu)化的結(jié)果嘞。

但是這個(gè)多層if else的形式引發(fā)了我的思考,因?yàn)槲乙苍陧?xiàng)目代碼中引入過如此繁重的if else結(jié)構(gòu),并在Code Review中被指出了問題。從那以后,我對if else的最大容忍層數(shù)就是三層。

我把大量if else的場景按照深度和廣度兩個(gè)維度劃分為兩種情況:

  • 嵌套層級過深
  • 平鋪范圍太廣

下面就討論一下,當(dāng)代碼中存在大量這樣結(jié)構(gòu)的代碼的時(shí)候,該如何優(yōu)化?

1.解決方案

1.1 盡早返回

又稱衛(wèi)語句,即Guard Statement

WikiPedia:

In computer programming, aguardis abooleanexpressionthat must evaluate to true if the program execution is to continue in the branch in question.

Regardless of which programming language is used, aguard clause,guard code, orguard statement, is a check of integritypreconditionsused to avoid errors during execution. A typical example is checking that a reference about to be processed is not null, which avoids null-pointer failures. Other uses include using a boolean field foridempotence(so subsequent calls are nops), as in thedispose pattern. The guard provides anearly exitfrom asubroutine, and is a commonly used deviation fromstructured programming, removing one level of nesting and resulting in flatter code:[1]replacingif guard { ... }withif not guard: return; ....

實(shí)際應(yīng)用:

if (CollectionUtils.isNotEmpty(list)) {
	// do something
} else {   
	return xxx;
}

使用盡早返回優(yōu)化:

if (CollectionUtils.isEmpty(list)) {
    return xxx;
}
// do something

可以看到,優(yōu)化后的代碼不僅節(jié)省了一個(gè)else語句,也能讓后續(xù)的"do something"節(jié)省一層if else包裹,代碼看起來更干凈一些

結(jié)合這個(gè)例子再說一下我對衛(wèi)語句的理解:

可以將“衛(wèi)”理解為“門衛(wèi)”,門衛(wèi)的作用是檢查過濾,只有符合條件的語句,才可以繼續(xù)執(zhí)行,否則直接勸返(return)。吐槽一下這種中文直譯有些晦澀,未免有點(diǎn)“德先生賽先生”的意思了。。。

1.2 使用switch或三元運(yùn)算符

可以利用語法知識,對if else進(jìn)行簡化,

例如,當(dāng)if else滿足一定條件時(shí):

if (condition1) {
    doSomeThing1();
} else if (condition2) {
    doSomeThing2();
} else if (condition3) {
    doSomeThing3(); 
} else if (condition4) {
    doSomeThing4();
} else {
    doSomeThing5(); 
}...

可以使用switch case語法進(jìn)行替換

或,

例如使用三元運(yùn)算符進(jìn)行賦值操作:

Integer num = obejct == null ? 1 : object.value();

1.3 策略模式

1.3.1 概念

策略模式是一種行為設(shè)計(jì)模式,即一個(gè)對象有一個(gè)確定的行為,在不同場景下,這些行為有不同的算法實(shí)現(xiàn)。

例如從內(nèi)蒙通過公共交通去北京是一個(gè)確定的行為,在天上這種場景可以選擇飛機(jī),地上的場景可以選擇火車~

策略模式一般包含三個(gè)要素:

  • 抽象策略(Abstract strategy):定義所謂的“確定的行為”,一般由接口或抽象類實(shí)現(xiàn)
  • 具體實(shí)現(xiàn)(Concrete strategy):封裝對應(yīng)場景下的具體算法實(shí)現(xiàn)。
  • 上下文(Context):負(fù)責(zé)具體實(shí)現(xiàn)策略的管理并供對象使用。

1.3.2 使用場景

一個(gè)接口或抽象類的各個(gè)子類都是為了解決相同的問題,區(qū)分這些子類的只有方法實(shí)現(xiàn)的不同。

代碼中使用大量if else或大面積switch case來選擇具體的子實(shí)現(xiàn)類

1.3.3 實(shí)際應(yīng)用

例如:

if ("man".equals(strategy)) {   
    // Perform related operations 
} else if ("woman".equals(strategy)) {   
    // Perform operations related to women
} else if ("other".equals(strategy)) {   
    // Perform other operations
}

上面一段代碼,每一個(gè)if分支完成的都是相同的操作,只是在不同的性別場景下,操作方法的實(shí)現(xiàn)不同,那么就可以使用策略模式進(jìn)行優(yōu)化:

首先,定義一個(gè)抽象策略接口:

public interface Strategy {
    void run() throws Exception;
}

然后,進(jìn)行不同策略的實(shí)現(xiàn):

//Men's strategy implementation class
@Slf4j
public class ManStrategy implements Strategy {
    @Override
    public void run() throws Exception {
        // Fast man's logic
        log.debug("Execute the logic related to men...");
    }
}
//Women's strategy implementation class
@Slf4j
public class WomanStrategy implements Strategy {
    @Override
    public void run() throws Exception {
        // Fast woman's logic
        log.debug("Execute women related logic...");
    }
}
//Others' policy implementation class
@Slf4j
public class OtherStrategy implements Strategy {
    @Override
    public void run() throws Exception {
        // Fast other logic
        log.debug("Perform other related logic...");
    }
}

最后,進(jìn)行策略的應(yīng)用:

public class StrategyTest {
    public static void main(String[] args) {
        try {
            Strategy strategy = initMap("man");
            strategy.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //Initialize the Map to obtain a gender policy
    private static Strategy initMap(String key) {
        //Use simple example
        HashMap<String, Strategy> map = new HashMap<>();
        map.put("man", new ManStrategy());
        map.put("woman", new WomanStrategy());
        map.put("other", new OtherStrategy());
        return map.get(key);
    }
}

1.3.4 優(yōu)劣勢分析及優(yōu)化

1.3.4.1 劣勢

整體上來看,使用策略模式雖然剔除了大量的if else語句,但是也引入了更多的類文件,同時(shí)在Context中需要維護(hù)一個(gè)類似注冊表的map對象,當(dāng)增加策略實(shí)現(xiàn)時(shí),容易忘記。

優(yōu)化措施:

在Java中,可以使用函數(shù)式編程進(jìn)行優(yōu)化:

@Slf4j
public class StrategyTest {
    public static void main(String[] args) {
        //Use simple example
        HashMap<String, Strategy> map = new HashMap<>();
        map.put("man", () -> log.debug("Execute the logic related to men..."));
        map.put("woman", () -> log.debug("Execute women related logic..."));
        map.put("other", () -> log.debug("Execute logic related to others..."));
        try {
            map.get("woman").run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

或者,使用枚舉進(jìn)行優(yōu)化:

@Slf4j
public enum Strategy {
    //Man state
    MAN(0) {
        @Override
        void run() {
            //Perform related operations
            log.debug("Execute the logic related to men");
        }
    },
    //Woman state
    WOMAN(1) {
        @Override
        void run() {
            //Perform operations related to women
            log.debug("Execute women related logic");
        }
    },
    //Other status
    OTHER(2) {
        @Override
        void run() {
            //Perform other related operations
            log.debug("Perform other related logic");
        }
    };
    abstract void run();
    public int statusCode;
    Strategy(int statusCode) {
        this.statusCode = statusCode;
    }
}
public static void main(String[] args) {
        try {
            //Simple use example
            String param = String.valueOf(Strategy.WOMAN);
            Strategy strategy = Strategy.valueOf(param);
            strategy.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
}

除此以外,在客戶端實(shí)際使用策略時(shí),即對象進(jìn)行方法的調(diào)用時(shí),客戶端必須知道這個(gè)策略的所有實(shí)現(xiàn)子類,并需要了解這些子類之間的不同以及各自的應(yīng)用場景,這樣客戶端才能選擇合適的策略實(shí)現(xiàn)“確定的行為”。

1.3.4.2 優(yōu)勢

最直接的好處就是可以讓又臭又長的if else代碼塊看起來更干凈。

面向?qū)ο蟮娜筇攸c(diǎn):封裝、繼承、多態(tài),在策略模式中都能找到影子。面向接口編程,代碼的可擴(kuò)展性好

代碼的可測性好,Mock更方便,減少了分支判斷,實(shí)現(xiàn)類只需要各自測試即可。

1.4 Optional

if else分支判斷的很多情況都是進(jìn)行非空條件的判斷,Optional是Java8開始提供的新特性,使用這個(gè)語法特性,也可以減少代碼中if else的數(shù)量,例如:

優(yōu)化前:

String str = "Hello World!";
if (str != null) {
    System.out.println(str);
} else {
    System.out.println("Null");
}

rust復(fù)制代碼String str = "Hello World!";

優(yōu)化后:

Optional<String> optional = Optional.of("Hello World!");
optional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));

1.5 注冊表

這種方式和策略模式有相似之處,但注冊表更自由,不需要提煉接口,只需要將自定義實(shí)現(xiàn)在注冊表中注冊即可。

例如,優(yōu)化前:

if (param.equals(value1)) {
    doAction1(someParams);
}else if (param.equals(value2)) {
    doAction2(someParams);
}else if (param.equals(value3)) {
    doAction3(someParams);
}

優(yōu)化后:

//Generic here? For the convenience of demonstration, it can be replaced with the real type we need in actual development
Map<?, Function<?> action> actionMappings = new HashMap<>(); 
// When init
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});
// Omit null judgment
actionMappings.get(param).apply(someParams);

1.6 責(zé)任鏈模式

先來看一段代碼:

public void handle(request) {
    if (handlerA.canHandle(request)) {
        handlerA.handleRequest(request);
    } else if (handlerB.canHandle(request)) {
        handlerB.handleRequest(request);
    } else if (handlerC.canHandle(request)) {
        handlerC.handleRequest(request);
    }
}

代碼中也是存在一坨if else語句,但是和上述例子不同之處在于,if條件判斷權(quán)在每個(gè)handler組件中,每一個(gè)handler的判斷方式也可能不盡相同,相當(dāng)靈活,同一個(gè)request可能同時(shí)滿足多個(gè)if條件

解決方案就是參考開源組件中Filter或者Interceptor責(zé)任鏈機(jī)制,優(yōu)化后代碼:

public void handle(request) {
  handlerA.handleRequest(request);
}
public abstract class Handler {
  protected Handler next;
  public abstract void handleRequest(Request request);
  public void setNext(Handler next) { this.next = next; }
}
public class HandlerA extends Handler {
  public void handleRequest(Request request) {
    if (canHandle(request)) doHandle(request);
    else if (next != null) next.handleRequest(request);
  }
}

2.總結(jié)&思考

這篇文章主要介紹了代碼中if else代碼塊泛濫時(shí)的治理措施,在實(shí)際應(yīng)用時(shí)可根據(jù)具體場景選擇合理的方案。

其實(shí)代碼中存在大面積if else本無問題,用一句網(wǎng)絡(luò)流行語來反駁就是:“你就說能不能用吧!”。但是作為有追求的工程師,我們要對項(xiàng)目以及代碼負(fù)責(zé),要及時(shí)的識別到代碼中的壞味道,并持續(xù)重構(gòu)優(yōu)化。最后還想說一定要擁抱開源,多研讀他人優(yōu)秀代碼,并臨摹、思考、實(shí)踐,日拱一卒,不期而至。

以上就是優(yōu)化Java代碼中if-else的方案分享的詳細(xì)內(nèi)容,更多關(guān)于Java優(yōu)化if-else的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中將String轉(zhuǎn)換為char數(shù)組的三種方式

    Java中將String轉(zhuǎn)換為char數(shù)組的三種方式

    這篇文章主要介紹了三種將字符串轉(zhuǎn)換為字符數(shù)組的方法,分別是toCharArray()、charAt()和循環(huán)、getChars(),每種方法都有其適用場景和優(yōu)缺點(diǎn),需要的朋友可以參考下
    2024-12-12
  • java微信支付接入流程詳解

    java微信支付接入流程詳解

    這篇文章主要為大家詳細(xì)介紹了java微信支付接入流程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 解決InputStream.available()獲取流大小問題

    解決InputStream.available()獲取流大小問題

    這篇文章主要介紹了解決InputStream.available()獲取流大小問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • spring aop execution表達(dá)式的用法

    spring aop execution表達(dá)式的用法

    這篇文章主要介紹了spring aop execution表達(dá)式的用法,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java無界阻塞隊(duì)列DelayQueue詳細(xì)解析

    Java無界阻塞隊(duì)列DelayQueue詳細(xì)解析

    這篇文章主要介紹了Java無界阻塞隊(duì)列DelayQueue詳細(xì)解析,DelayQueue是一個(gè)支持時(shí)延獲取元素的無界阻塞隊(duì)列,隊(duì)列使用PriorityQueue來實(shí)現(xiàn),隊(duì)列中的元素必須實(shí)現(xiàn)Delayed接口,在創(chuàng)建元素時(shí)可以指定多久才能從隊(duì)列中獲取當(dāng)前元素,需要的朋友可以參考下
    2023-12-12
  • MyBatis配置文件解析與MyBatis實(shí)例演示

    MyBatis配置文件解析與MyBatis實(shí)例演示

    這篇文章主要介紹了MyBatis配置文件解析與MyBatis實(shí)例演示以及怎樣編譯安裝MyBatis,需要的朋友可以參考下
    2022-04-04
  • Java中BigDecimal類的add()的使用詳解

    Java中BigDecimal類的add()的使用詳解

    這篇文章主要介紹了Java中BigDecimal類的add()的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • springboot聚合工程的部署與深入講解

    springboot聚合工程的部署與深入講解

    最近在寫一個(gè)商城,使用Maven聚合工程來管理,但是其中搭建環(huán)境遇見了各種的坑,下面這篇文章主要給大家介紹了關(guān)于springboot聚合工程部署的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • IntelliJ IDEA maven 構(gòu)建簡單springmvc項(xiàng)目(圖文教程)

    IntelliJ IDEA maven 構(gòu)建簡單springmvc項(xiàng)目(圖文教程)

    在工作當(dāng)中,我們有時(shí)需要創(chuàng)建一個(gè)全新的工程,而基于spring-mvc web的工程較為常見,這篇文章主要介紹了IntelliJ IDEA maven 構(gòu)建簡單springmvc項(xiàng)目(圖文教程),感興趣的小伙伴們可以參考一下
    2018-05-05
  • IDEA如何實(shí)現(xiàn)批量修改變量名

    IDEA如何實(shí)現(xiàn)批量修改變量名

    這篇文章主要介紹了IDEA如何實(shí)現(xiàn)批量修改變量名問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11

最新評論