防御性编程失败,我开始优化我写的多重 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

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu