java去除if...else的七種方法總結(jié)
方法一:提前 return
假如有如下代碼:
if (condition){
doSomething;
} else {
return;
}
這種代碼我們一般采用提前 return 的方式,去掉不必要的 else。
if (!condition){
return
}
doSomething;
這種方法一般只適合分支結(jié)構(gòu)很簡單的 if...else,我們可以提前 return ,把一些不必要的 if...else 去掉。
方法二:枚舉
枚舉其實(shí)也是可以去掉 if...else 的,如下:
String orderStatusDes;
if ("1".equals(orderStatus)) {
orderStatusDes = "訂單未支付";
} else if ("2".equals(orderStatus)) {
orderStatusDes = "訂單已支付";
} else if ("3".equals(orderStatus)) {
orderStatusDes = "訂單已發(fā)貨";
} else if ("4".equals(orderStatus)) {
orderStatusDes = "訂單已簽收";
} else if ("5".equals(orderStatus)) {
orderStatusDes = "訂單已評(píng)價(jià)";
}
可能有小伙伴說,靠,誰會(huì)寫這種代碼?別這么絕對(duì),大明哥工作這么久了,到現(xiàn)在依然看到有工作 5 、6 年的人寫這樣的代碼。這種類型的代碼非常適合枚舉來解決。
先定義一個(gè)枚舉類:
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
UN_PAID("1","訂單未支付"),
PAIDED("2","訂單已支付"),
SENDED("3","訂單已發(fā)貨"),
SINGED("4","訂單已簽收"),
EVALUATED("5","訂單已評(píng)價(jià)");
private String status;
private String statusDes;
static OrderStatusEnum of(String status) {
for (OrderStatusEnum statusEnum : OrderStatusEnum.values()) {
if (statusEnum.getStatus().equals(status)) {
return statusEnum;
}
}
return null;
}
}
有了這個(gè)枚舉,上面代碼直接可以優(yōu)化為一行代碼:
String orderStatusDes = OrderStatusEnum.of(orderStatus).getStatusDes();
當(dāng)然一般在實(shí)際項(xiàng)目中,這種處理方式也不是最佳的,最佳的方式應(yīng)該是在數(shù)據(jù)庫里面有一個(gè)碼值配置表,然后加載到系統(tǒng)緩存中來,在通過 code 去取值。當(dāng)然枚舉也是一種很好的解決方案。
方案三:Optional 判空
我相信各位小伙伴的項(xiàng)目里面一定存在非空判斷,如果為空,則拋出異常或者 return。
Order order = getOrderById(id);
if (order == null) {
return "-1";
} else {
return order.getOrderStatus();
}
對(duì)于這種代碼我們利用 Optional 可以非常優(yōu)雅地解決。
return Optional.ofNullable(order).map(o -> o.getOrderStatus()).orElse("-1");
這種方式是不是非常優(yōu)雅,有格調(diào)。最后補(bǔ)充一句:
防止 NPE,是程序員的基本修養(yǎng)
方案四:表驅(qū)動(dòng)法
表驅(qū)動(dòng)法,是一種讓你可以在表中查找信息,而不必用過多的 if...else 來把他們找出來的方法。如下:
if ("code1".equals(action)) {
doAction1();
} else if ("code2".equals(action)) {
doAction2();
} else if ("code3".equals(action)) {
doAction3();
} else if ("code4".equals(action)) {
doAction4();
} else if ("code5".equals(action)) {
doAction5();
}
優(yōu)化方法如下:
Map<String, Function<?> action> actionMap = new HashMap<>();
action.put("code1",() -> {doAction1()});
action.put("code2",() -> {doAction2()});
action.put("code3",() -> {doAction3()});
action.put("code4",() -> {doAction4()});
action.put("code5",() -> {doAction5()});
// 使用
actionMap.get(action).apply();
其實(shí)這種方式也不是很好,因?yàn)樗鼤?huì)顯得代碼非常臃腫。一種變形方案是將 doAction() 抽象成類。如下:
//1. 先定義一個(gè) ActionService 接口
public interface ActionService {
void doAction();
}
//2. 然后定義 5 個(gè)實(shí)現(xiàn)類
public class ActionService1 implements ActionService{
public void doAction() {
//do something
}
}
//3. 加入表中
Map<String, ActionService> actionMap = new HashMap<>();
action.put("code1",new ActionService1());
action.put("code2",new ActionService2());
action.put("code3",new ActionService3());
action.put("code4",new ActionService4());
action.put("code5",new ActionService5());
//4. 調(diào)用
actionMap.get(action).doAction();
這種方式是不是比較優(yōu)雅些!
方案五:策略模式 + 工廠方法
策略模式 + 工廠方法是解決 if...else 用得非常多的方案,它和上面的表驅(qū)動(dòng)法有點(diǎn)兒類似。使用策略模式 + 工廠方法分為幾個(gè)步驟,以上面例子為例:
把條件模塊抽象為一個(gè)公共的接口,策略接口
public interface ActionService {
void doAction();
}
根據(jù)每個(gè)邏輯,定義出自己具體的策略實(shí)現(xiàn)類,如下:
public class ActionService1 implements ActionService{
public void doAction() {
//do something
}
}
public class ActionService2 implements ActionService{
public void doAction() {
//do something
}
}
// 省略其他策略
工廠類,統(tǒng)一調(diào)度,用來管理這些策略,如下:
public class ActionServiceFactory {
private ActionServiceFactory(){
}
private static class SingletonHolder{
private static ActionServiceFactory instance=new ActionServiceFactory();
}
public static ActionServiceFactory getInstance(){
return SingletonHolder.instance;
}
private static final Map<String,ActionService> ACTION_SERVICE_MAP = new HashMap<String, ActionService>();
static {
ACTION_SERVICE_MAP.put("action1",new ActionService1());
ACTION_SERVICE_MAP.put("action2",new ActionService2());
ACTION_SERVICE_MAP.put("action3",new ActionService3());
ACTION_SERVICE_MAP.put("action4",new ActionService4());
ACTION_SERVICE_MAP.put("action5",new ActionService5());
}
public static ActionService getActionService(String actionCode) {
ActionService actionService = ACTION_SERVICE_MAP.get(actionCode);
if (actionService == null) {
throw new RuntimeException("非法 actionCode");
}
return actionService;
}
public void doAction(String actionCode) {
getActionService(actionCode).doAction();
}
}
單例模式實(shí)現(xiàn)工廠類。
使用
ActionServiceFactory.getInstance().doAction("action1");
這種優(yōu)化方式也是很優(yōu)雅的,特別適合分支較多,邏輯較為復(fù)雜的代碼塊,這種方式將分支邏輯與業(yè)務(wù)代碼解耦了,是一種很不錯(cuò)的方案。
方案六:責(zé)任鏈模式
你想不到責(zé)任鏈模式也能優(yōu)化 if...else 吧。責(zé)任鏈我們可以看做是一個(gè)單鏈表的數(shù)據(jù)結(jié)構(gòu),一個(gè)對(duì)象一個(gè)對(duì)象地過濾條件,符合的就執(zhí)行,然后結(jié)束,不符合的就傳遞到下一個(gè)節(jié)點(diǎn),如果每個(gè)對(duì)象都無法處理,一般都有一個(gè)最終的節(jié)點(diǎn)來統(tǒng)一處理。
我們依然以上面那個(gè)例子為例。
定義責(zé)任鏈處理請(qǐng)求節(jié)點(diǎn)
public abstract class ActionHandler {
// 后繼節(jié)點(diǎn)
protected ActionHandler successor;
/**
* 處理請(qǐng)求
* @param actionCode
*/
public void handler(String actionCode) {
doHandler(actionCode);
}
// 設(shè)置后繼節(jié)點(diǎn)
protected ActionHandler setSuccessor(ActionHandler successor) {
this.successor = successor;
return this;
}
// 處理請(qǐng)求
public abstract void doHandler(String actionCode);
}
定義首尾節(jié)點(diǎn),用于一些異常情況的處理
// 首節(jié)點(diǎn),判斷 actionCode 是否為空
public class HeadHandler extends ActionHandler{
@Override
public void doHandler(String actionCode) {
if (StringUtils.isBlank(actionCode)) {
throw new RuntimeException("actionCode 不能為空");
}
successor.doHandler(actionCode);
}
}
// 尾節(jié)點(diǎn),直接拋出異常,因?yàn)榈搅宋补?jié)點(diǎn)說明當(dāng)前 code 沒有處理
public class TailHandler extends ActionHandler{
@Override
public void doHandler(String actionCode) {
throw new RuntimeException("當(dāng)前 code[" + actionCode + "] 沒有具體的 Handler 處理");
}
}
定義各個(gè)節(jié)點(diǎn)具體的實(shí)現(xiàn)節(jié)點(diǎn)
public class ActionHandler1 extends ActionHandler{
@Override
public void doHandler(String actionCode) {
if ("action1".equals(actionCode)) {
doAction1();
} else {
// 傳遞到下一個(gè)節(jié)點(diǎn)
successor.doHandler(actionCode);
}
}
}
public class ActionHandler2 extends ActionHandler{
@Override
public void doHandler(String actionCode) {
if ("action2".equals(actionCode)) {
doAction2();
} else {
// 傳遞到下一個(gè)節(jié)點(diǎn)
successor.doHandler(actionCode);
}
}
}
// 省略其他節(jié)點(diǎn)
定義工廠,來構(gòu)建一條完整的責(zé)任鏈,并負(fù)責(zé)調(diào)度
public class ActionHandlerFactory {
private ActionHandler headHandler;
private ActionHandlerFactory(){
headHandler = new HeadHandler();
ActionHandler actionHandler1 = new ActionHandler1();
ActionHandler actionHandler2 = new ActionHandler2();
ActionHandler actionHandler3 = new ActionHandler3();
ActionHandler actionHandler4 = new ActionHandler4();
ActionHandler actionHandler5 = new ActionHandler5();
ActionHandler tailHandler = new TailHandler();
// 構(gòu)建一條完整的責(zé)任鏈
headHandler.setSuccessor(actionHandler1).setSuccessor(actionHandler2).setSuccessor(actionHandler3).
setSuccessor(actionHandler4).setSuccessor(actionHandler5).setSuccessor(tailHandler);
}
private static class SingletonHolder{
private static ActionHandlerFactory instance=new ActionHandlerFactory();
}
public static ActionHandlerFactory getInstance(){
return SingletonHolder.instance;
}
public void doAction(String actionCode) {
headHandler.doHandler(actionCode);
}
}
使用
ActionHandlerFactory.getInstance().doAction("action1");
方案七:Function
Function 是 Java 8 中的函數(shù)式接口,利用好它我們可以極大地簡化我們的代碼,例如利用它我們可以輕松去掉我們的 if...else。比如有下面一段代碼:
// 拋出異常
if (...) {
throw new RuntimeException("哎呀,有異常哦...")
}
// if...else 分支
if(...) {
doSomething1();
} else {
doSomething2();
}
現(xiàn)在我們利用 Function 來處理上面兩段代碼
處理拋出異常
定義拋出異常的形式的函數(shù)式接口
@FunctionalInterface
public interface ThrowExceptionFunction {
/**
* 拋出異常
* @param message
*/
void throwMessage(String message);
}
這里只需要有一個(gè)這樣的函數(shù)式接口就行,而且方法也沒有返回值,是一個(gè)消費(fèi)型接口。
增加判斷工具類
public class ValidateUtils {
/**
* 拋出異常
* @param flag
* @return
*/
public static ThrowExceptionFunction isTrue(Boolean flag) {
return (errorMessage) -> {
if (flag) {
throw new RuntimeException(errorMessage);
}
};
}
}
ValidateUtils 類也是非常簡單的,如果傳入的 flag 為 true,則拋出異常。isTrue() 返回值也是剛剛我們定義的 ThrowExceptionFunction。
使用
ValidateUtils.isTrue(flag).throwMessage("哎呀,有異常哦...");
使用方式是不是非常簡單?
處理 if...else 分支
其實(shí)使用 Function 來去掉 if...else 分支我認(rèn)為有點(diǎn)兒偏門,因?yàn)樗浅R蕾囄覀兌x的 Function 函數(shù),比如我們定義的方法只有兩個(gè)參數(shù),那它就只能處理處理兩個(gè)分支的,對(duì)于三個(gè)分支的 if...else 則需要重新定義方法。下面以兩個(gè)分支為例。
定義函數(shù)式接口
@FunctionalInterface
public interface ActionHandler {
void doActionHandler(ActionService trueActionService,ActionService falseActionService);
}
函數(shù)式接口中定義了一個(gè)方法,doActionHandler(),它有兩個(gè)參數(shù),分別為:
- trueActionService:為 true 時(shí)要進(jìn)行的操作
- falseActionService:為 false 時(shí)要進(jìn)行的操作
定義判斷方法
增加一個(gè)工具類,用來判斷為 true 時(shí)執(zhí)行哪個(gè)方法,為 false 時(shí)執(zhí)行哪個(gè)方法。
public class ActionHandlerUtils {
public static ActionHandler isTrue(Boolean flag) {
return (trueActionService,falseActionService) -> {
if (flag) {
trueActionService.doAction();
} else {
trueActionService.doAction();
}
};
}
}
使用
ActionHandlerUtils.isTrue(true)
.doActionHandler(() -> {
//do true Something
},() ->{
//do false Something
});
總結(jié)
大明哥在這里總結(jié)了 7 中方式用來解決 if...else 的問題,我相信里面總有一兩種方案是你比較滿意的,七種方案各有優(yōu)劣,各自有各自的使用場景,我們需要在實(shí)踐中不斷領(lǐng)悟,在重構(gòu)中不斷進(jìn)化,總結(jié)出適合自己最佳的重構(gòu)方案。
到此這篇關(guān)于java去除if...else的七種方法總結(jié)的文章就介紹到這了,更多相關(guān)java去除if else內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的區(qū)
這篇文章主要介紹了com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的區(qū)別以及設(shè)定serverTimezone的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
springboot實(shí)現(xiàn)調(diào)用百度ocr實(shí)現(xiàn)身份識(shí)別+二要素校驗(yàn)功能
本文介紹了如何使用Spring Boot調(diào)用百度OCR服務(wù)進(jìn)行身份識(shí)別,并通過二要素校驗(yàn)確保信息準(zhǔn)確性,感興趣的朋友一起看看吧2025-03-03
使用Apache POI在Java中實(shí)現(xiàn)Excel單元格的合并
在日常工作中,Excel是一個(gè)不可或缺的工具,尤其是在處理大量數(shù)據(jù)時(shí),本文將介紹如何使用 Apache POI 庫在 Java 中實(shí)現(xiàn) Excel 單元格的合并,需要的可以了解下2025-03-03

