防御性编程失败,我开始优化我写的多重 if-else 代码

2024-01-06 04:20

本文主要是介绍防御性编程失败,我开始优化我写的多重 if-else 代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 版本
  • 几种常用的优化方式
    • 提前使用 return 返回去除不必要的 else
    • 使用三目运算符
    • 使用枚举
    • 抽取条件判断作为单独的方法
    • 有时候 switch 比 if-else 更加合适
    • 策略模式 + 简单工厂模式
  • 如何优化开头的代码
  • 个人简介

前言

  • 最近防御性编程比较火,不信邪的我在开发中我进行了尝试,然后我写下了如下的代码:
    public static void main(String[] args) {// do somethingif ("满足条件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 somethingreturn false;}else {// do somethingreturn true;}}
  • 优化后
    private static boolean extracted(boolean condition) {if (condition) {// do somethingreturn false;}// do somethingreturn 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 somethingif ("满足条件A" && "满足条件B") {// 查询权限if ("是否具备权限A" && "是否具备权限B") {// do something}}// do something
  • 优化后
    public static void main(String[] args) {// do somethingif (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 {@Overridepublic void notifyUser(String message) {System.out.println("通过渠道A发送通知:" + message);}
}// 实现具体的通知渠道B
class ChannelB implements NotificationChannel {@Overridepublic void notifyUser(String message) {System.out.println("通过渠道B发送通知:" + message);}
}// 实现具体的通知渠道C
class ChannelC implements NotificationChannel {@Overridepublic 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 somethingif (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编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

这篇关于防御性编程失败,我开始优化我写的多重 if-else 代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/575194

相关文章

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

MySQL索引的优化之LIKE模糊查询功能实现

《MySQL索引的优化之LIKE模糊查询功能实现》:本文主要介绍MySQL索引的优化之LIKE模糊查询功能实现,本文通过示例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前缀匹配优化二、后缀匹配优化三、中间匹配优化四、覆盖索引优化五、减少查询范围六、避免通配符开头七、使用外部搜索引擎八、分

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

使用Python实现全能手机虚拟键盘的示例代码

《使用Python实现全能手机虚拟键盘的示例代码》在数字化办公时代,你是否遇到过这样的场景:会议室投影电脑突然键盘失灵、躺在沙发上想远程控制书房电脑、或者需要给长辈远程协助操作?今天我要分享的Pyth... 目录一、项目概述:不止于键盘的远程控制方案1.1 创新价值1.2 技术栈全景二、需求实现步骤一、需求

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

Pyserial设置缓冲区大小失败的问题解决

《Pyserial设置缓冲区大小失败的问题解决》本文主要介绍了Pyserial设置缓冲区大小失败的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录问题描述原因分析解决方案问题描述使用set_buffer_size()设置缓冲区大小后,buf