如何優化代碼中大量的if/else,switch/case?

前言

隨着項目的迭代,代碼中存在的分支判斷可能會愈來愈多,當裏面涉及到的邏輯比較複雜或者分支數量實在是多的難以維護的時候,咱們就要考慮下,有辦法能讓這些代碼變得更優雅嗎?java

正文

使用枚舉

這裏咱們簡單的定義一個表示狀態的枚舉。git

public enum Status {
    NEW(0),RUNNABLE(1),RUNNING(2),BLOCKED(3),DEAD(4);

    public int statusCode;

    Status(int statusCode){
        this.statusCode = statusCode;
    }
}
複製代碼

那麼咱們在使用的時候就能夠直接經過枚舉調用了。github

int statusCode = Status.valueOf("NEW").statusCode;
複製代碼

優雅的解決了下面代碼賦值的方式編程

if(param.equals("NEW")){
    statusCode = 0;
}else if(param.equals("RUNNABLE")){
    statusCode = 1;
}
...
複製代碼

善用 Optional

在項目中,總少不了一些非空的判斷,可能大部分人仍是以下的用法設計模式

if(null == user){
    //action1
}else{
    //action2
}
複製代碼

這時候該掏出Optional這個祕密武器了,它可讓非空校驗更加優雅,間接的減小if操做。沒了解過Optional的同窗可自行Google,這裏就再也不贅述。數組

Optional<User> userOptional = Optional.ofNullable(user);
userOptional.map(action1).orElse(action2);
複製代碼

上面的代碼跟第一段是等效的,經過一些新特性讓代碼更加緊湊。app

表驅動法

來自Google的解釋:表驅動法是一種編程模式,它的本質是,從表裏查詢信息來代替邏輯語句(if,case)。下面看一個案例,經過月份來獲取當月的天數(僅做爲案例演示,獲取2月份的數據不嚴謹),普通作法:異步

int getMonthDays(int month){
	switch(month){
		case 1:return 31;break;
		case 2:return 29;break;
		case 3:return 31;break;
		case 4:return 30;break;
		case 5:return 31;break;
		case 6:return 30;break;
		case 7:return 31;break;
		case 8:return 31;break;
		case 9:return 30;break;
		case 10:return 31;break;
		case 11:return 30;break;
		case 12:return 31;break;
		defaultreturn 0;
	}
}
複製代碼

表驅動法實現方式post

int monthDays[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int getMonthDays(int month){
	return monthDays[--month];
}
複製代碼

其實這裏的表就是數組而已,經過直接查詢數組來得到須要的數據,那麼同理,Map之類的容器也能夠成爲咱們編程概念中的表。優化

Map<?, Function<?> action> actionsMap = new HashMap<>();

// 初試配置對應動做
actionsMap.put(value1, (someParams) -> { doAction1(someParams)});
actionsMap.put(value2, (someParams) -> { doAction2(someParams)});
actionsMap.put(value3, (someParams) -> { doAction3(someParams)});
 
// 省略 null 判斷
actionsMap.get(param).apply(someParams);
複製代碼

經過Java8的lambda表達式,咱們把須要執行東西存進value中,調用的時候經過匹配key的方式進行。

提早判斷返回

在以前的文章《優化代碼中的「壞味道」》裏也有提過,以下語句

if(condition){
   //dost
}else{
   return ;
}
複製代碼

改成

if(!condition){
   return ;
}
//dost
複製代碼

避免一些沒必要要的分支,讓代碼更精煉。

其餘方法

除了上面提到的方法,咱們還能夠經過一些設計模式,例如策略模式,責任鏈模式等來優化存在大量if,case的狀況,其原理會和表驅動的模式比較類似,你們能夠本身動手實現一下,例如咱們在Netty的使用過程當中,可能會出現須要大量判斷不一樣的命令去執行對應動做的場景。

ServerHandler.java if(command.equals("login")){
    //執行登陸
}else if(command.equals("chat")){
    //聊天
}else if(command.equals("broadcast")){
    //廣播信息
}
....
複製代碼

該如何處理呢?這裏先賣個關子,你們能夠先思考一下,筆記後續會寫一些關於Netty實現IM的文章,到時候會詳細介紹。

結語

最後要明確一點,不是全部的if/else,switch/case都須要優化,當咱們發現有「痛點」或者「聞到代碼有壞味道」再來優化纔是最好的,否則你可能會寫了一個從不擴展的可擴展代碼,全部的優化都是爲了更好的迭代項目,更好的服務於業務,而不是爲了優化而優化。


公衆號博文同步Github倉庫,有興趣的朋友能夠幫忙給個Star哦,碼字不易,感謝支持。

github.com/PeppaLittle…

推薦閱讀

如何提升使用Java反射的效率?
Java日誌正確使用姿式
大白話搞懂什麼是同步/異步/阻塞/非阻塞
論JVM爆炸的幾種姿式及自救方法

有收穫的話,就點個贊吧

關注「深夜裏的程序猿」,分享最乾的乾貨

相關文章
相關標籤/搜索