前言

  • 最近防御性编程比较火,不信邪的我在开发中我进行了测验,然后我写下了如下的代码:
    public static void main(String[] args) {
        // do something
        if ("满意条件A") {
            // 查询权限
            if ("是否具有权限A" && "是否具有权限B") {
                // 查询装备
                if ("装备是否敞开"){
                    // do something
                }
            }
        }
        // do something
    }
  • 不出意外我被逮捕了,组内另外一位搭档对我的代码进行了 CodeReview,我的防御性编程编程没有幸运逃脱,被符号上了“多重 if-else ”需求进行优化,至此我的第一次防御性编程失败,开始了优化多重 if-else 之路,下面是我总结出的常用几种优化办法。

版本

  • Java8

几种常用的优化办法

提早运用 return 回来去除不必要的 else

  • 如果咱们的代码块中需求运用 return 回来,咱们应该尽可能早的运用 return 回来而不是运用 else
  • 优化前
    private static boolean extracted(boolean condition) {
        if (condition) {
            // do something
            return false;
        }else {
            // do something
            return true;
        }
    }
  • 优化后
    private static boolean extracted(boolean condition) {
        if (condition) {
            // do something
            return false;
        }
        // do something
        return true;
    }

运用三目运算符

  • 一些简略的逻辑咱们能够运用三目运算符代替 if-else ,这样能够让咱们的代码愈加简练

  • 优化前

        int num = 0;
        if (condition) {
            num = 1;
        } else {
            num = 2;
        }
  • 优化后
int num = condition ? 1 : 2;

运用枚举

  • 在某一些场景咱们也能够运用枚举来优化多重 if-else 代码,使咱们的代码愈加简练、具有更多的可读性和可维护性。

  • 优化前

        String OrderStatusDes;
        if (orderStatus == 0) {
            OrderStatusDes = "订单未付出";
        } else if (orderStatus == 1) {
            OrderStatusDes = "订单已付出";
        } else if (orderStatus == 2) {
            OrderStatusDes = "已发货";
        } else {
            throw new Exception("Invalid order status");
        }
  • 优化后
public enum OrderStatusEnum {
    UN_PAID(0, "订单未付出"),
    PAIDED(1, "订单已付出"),
    SENDED(2, "已发货"),
    ;
    private final int code;
    private final String desc;
    public int getCode() {
        return code;
    }
    public String getDesc() {
        return desc;
    }
    OrderStatusEnum(int index, String desc) {
        this.code = index;
        this.desc = desc;
    }
    public static OrderStatusEnum getOrderStatusEnum(int orderStatusCode) {
        for (OrderStatusEnum statusEnum : OrderStatusEnum.values()) {
            if (statusEnum.getCode() == orderStatusCode) {
                return statusEnum;
            }
        }
        return null;
    }
}
// 当然你需求依据事务场景对异常值做出适宜的处理
OrderStatusEnum.getOrderStatusEnum(2)

抽取条件判别作为独自的办法

  • 当咱们某个逻辑条件判别比较复杂时,能够考虑将判别条件抽离为独自的办法,这样能够使咱们主流程逻辑愈加清晰
  • 优化前
        // do something
        if ("满意条件A" && "满意条件B") {
            // 查询权限
            if ("是否具有权限A" && "是否具有权限B") {
                // do something
            }
        }
        // do something
  • 优化后
    public static void main(String[] args) {
        // do something
        if (hasSomePermission()) {
            // do something
        }
        // do something
    }
    private static boolean hasSomePermission() {
        if (!"满意条件A" || !"满意条件B") {
            return false;
        }
        // 查询权限
        return "是否具有权限A" && "是否具有权限B";
    }

有时候 switch 比 if-else 愈加适宜

  • 当条件为清晰的变量和枚举、或许单值匹配时,switch 比 if-else 愈加适宜,能够咱们带好更好的可读性以及更好的功能 O(1)
  • 优化前
if (day == Day.MONDAY) {
    // 处理星期一的逻辑
} else if (day == Day.TUESDAY) {
    // 处理星期二的逻辑
} else if (day == Day.WEDNESDAY) {
    // 处理星期三的逻辑
} else if (day == Day.THURSDAY) {
    // 处理星期四的逻辑
} else if (day == Day.FRIDAY) {
    // 处理星期五的逻辑
} else if (day == Day.SATURDAY) {
    // 处理星期六的逻辑
} else if (day == Day.SUNDAY) {
    // 处理周日的逻辑
} else {
    // 处理其他情况
}
  • 优化后
// 运用 switch 处理枚举类型
switch (day) {
    case MONDAY:
        // 处理星期一的逻辑
        break;
    case TUESDAY:
        // 处理星期二的逻辑
        break;
    // ...
    default:
        // 处理其他情况
        break;
}

战略形式 简略工厂形式

  • 前面咱们介绍一些常规、比较简略的优化办法,但是在一些愈加复杂的场景(比方多途径对接、多方案完成等)咱们能够结合一些场景的设计形式来完成让咱们的代码愈加高雅和可维护性,比方战略形式 简略工厂形式。

  • 优化前

    public static void main(String[] args) {
        // 比方咱们商场有多个告诉途径
        // 咱们需求依据不同的条件运用不同的告诉途径
        if ("满意条件A") {
            // 构建途径A
            // 告诉
        } else if ("满意条件B") {
            // 构建途径B
            // 告诉
        } else {
            // 构建途径C
            // 告诉
        }
    }
// 上面的代码不只维护起来麻烦同时可读性也比较差,咱们能够运用战略形式   简略工厂形式
  • 优化后
import java.util.HashMap;
import java.util.Map;
// 界说告诉途径接口
interface NotificationChannel {
    void notifyUser(String message);
}
// 完成详细的告诉途径A
class ChannelA implements NotificationChannel {
    @Override
    public void notifyUser(String message) {
        System.out.println("经过途径A发送告诉:"   message);
    }
}
// 完成详细的告诉途径B
class ChannelB implements NotificationChannel {
    @Override
    public void notifyUser(String message) {
        System.out.println("经过途径B发送告诉:"   message);
    }
}
// 完成详细的告诉途径C
class ChannelC implements NotificationChannel {
    @Override
    public void notifyUser(String message) {
        System.out.println("经过途径C发送告诉:"   message);
    }
}
// 告诉途径工厂
class NotificationChannelFactory {
    private static final Map<String, Class<? extends NotificationChannel>> channelMap = new HashMap<>();
    static {
        channelMap.put("A", ChannelA.class);
        channelMap.put("B", ChannelB.class);
        channelMap.put("C", ChannelC.class);
    }
    public static NotificationChannel createChannel(String channelType) {
        try {
            Class<? extends NotificationChannel> channelClass = channelMap.get(channelType);
            if (channelClass == null) {
                throw new IllegalArgumentException("不支持的告诉途径类型");
            }
            return channelClass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException("无法创建告诉途径", e);
        }
    }
}
// 客户端代码
public class NotificationClient {
    public static void main(String[] args) {
        // 依据条件挑选告诉途径类型
        String channelType = "A";
        // 运用简略工厂创建告诉途径
        NotificationChannel channel = NotificationChannelFactory.createChannel(channelType);
        // 履行告诉
        channel.notifyUser("这是一条告诉音讯");
    }
}
  • 有时候咱们还能够凭借 Spring IOC 能力的自动完成战略类的导入,然后运用 getBean() 办法获取对应的战略类实例,能够依据咱们的实际情况灵活挑选。

如何优化开头的代码

  • 好了现在回到开头,如果是你会进行怎样优化,下面是我交出的答卷,大家也能够在评论区宣布自己的观点,欢迎一同沟通:
   public static void main(String[] args) {
        // do something
        if (isMeetCondition()) {
            // 查询装备
            // 此处查询装备的值需求在详细的使命中运用,所有并没抽离
            if ("装备是否敞开") {
                // do something
            }
        }
        // do something
    }
    /**
     * 判别是否满意履行条件
     */
    private static boolean isMeetCondition() {
        if (!"满意条件A") {
            return false;
        }
        // 查询权限
        return "是否具有权限A" && "是否具有权限B";
    }

个人简介

你好,我是 Lorin 洛林,一位 Java 后端技能开发者!座右铭:Technology has the power to make the world a better place.

我对技能的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技能趋势的地方。

作为一个 Java 后端技能爱好者,我不只热衷于探究言语的新特性和技能的深度,还热衷于分享我的见地和最佳实践。我相信常识的分享和社区协作能够帮助咱们共同生长。

在我的博客上,你将找到关于Java中心概念、JVM 底层技能、常用结构如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等音讯中间件、功能优化等内容的深化文章。我也将分享一些编程技巧和解决问题的办法,以帮助你更好地把握Java编程。

我鼓舞互动和树立社区,因而请留下你的问题、主张或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技能资讯,以保证你与技能国际的最新开展坚持联系。我等待与你一同在技能之路上前进,一同探讨技能国际的无限可能性。

坚持关注我的博客,让咱们共同追求技能杰出。