公司新来的同事给出了if-else优化的8种方案

我们日常开发的项目中,如果代码中存在大量的if-else语句,阅读起来非常的折磨(直接劝退),维护起来也很难,也特别容易出问题。比如说以下:
ifelse垃圾代码.png

接下来,本文介绍我们常使用的8种方法去优化if-else。

ifelse优化方案.png

1、提前return,让正常流程走主干

如果if-else代码中包含return语句,或者我们可以将包含if-else的代码从主干中抽取到一个单独方法,这样就可以在这个方法中可以return掉。这中思想也是短路求值的一种体现。把多余 else 干掉,使代码更加优雅。

  • 优化前代码:
// 主流程代码  
if (condition){  
	// doSomething  
}else {  
	return;  
}
// 主流程代码  
if (condition){  
// doSomething1  
}else {  
// doSomething2  
}
  • 优化后代码:
// 主流程代码  
if (!condition){  
	return;  
}  
 // doSomething
// 主流程代码  
//doSomething  
doSomething();

private static void doSomething(){  
	// 主流程代码  
	if (!condition){  
	// doSomething1  
	return;  
	}  
	// doSomething2  
}

2、使用三目运算符

某些if-else可以优化为使用三目运算符,这样会让代码更简洁,可读性高。

  • 优化前
int price;  
if (condition1){  
	price = 1;  
} else if (condition2) {  
	price = 2;  
}else {  
	price = 0;  
}
  • 优化后
int price = condition1 ? 1 : (condition2 ? 2 : 0);

3、使用Optional

我们在代码中判null会导致存在大量的if-else,这个时候我们可以考虑使用Java8的Optional去优化。

  • 优化前
public static void main(String[] args) {  
	String s = handleStr("11");  
	System.out.println(s);  
}  
  
private static String handleStr(String str){  
	if (str != null){  
	return str.concat("。。。。。");  
	}else {  
	return "Null";  
	}  
}
  • 优化后代码:
public static void main(String[] args) {
	String s = Optional.ofNullable(handleStr("11"))
					   .map(str -> str.concat("。。。。。"))
					   .orElse("Null");

	System.out.println(s);
}

private static String handleStr(String str) {
	// 其余业务逻辑,同样适用于处理一个对象,判null
	return str;
}

4、多态

我们可以将一些操作(比如一些状态)的一些共性的方法抽象成一个公共接口,然后针对这些操作实现这些接口完成不同的逻辑,在调用时我们只需要传入对应的操作类即可,对外的操作方法都是同一个。

  • 优化前代码
public class OrderProcessing {
    public static void main(String[] args) {
        processOrder("pending");
        processOrder("paid");
        processOrder("shipped");
    }

    private static void processOrder(String status) {
        if ("pending".equalsIgnoreCase(status)) {
            System.out.println("Handling payment for pending order.");
            // 处理支付逻辑
            System.out.println("Payment handled.");
            System.out.println("Cannot ship. Payment pending.");
        } else if ("paid".equalsIgnoreCase(status)) {
            System.out.println("Payment already received.");
            System.out.println("Handling shipping for paid order.");
            // 处理发货逻辑
            System.out.println("Order shipped.");
        } else if ("shipped".equalsIgnoreCase(status)) {
            System.out.println("Payment already received.");
            System.out.println("Order already shipped.");
        } else {
            System.out.println("Invalid order status: " + status);
        }
    }
}

  • 优化后代码
// 状态接口
interface OrderState {
    void handlePayment();

    void handleShipping();
}

// 具体状态类
class PendingPaymentState implements OrderState {
    @Override
    public void handlePayment() {
        System.out.println("Payment handled for pending order.");
    }

    @Override
    public void handleShipping() {
        System.out.println("Cannot ship. Payment pending.");
    }
}

class PaidState implements OrderState {
    @Override
    public void handlePayment() {
        System.out.println("Payment already received.");
    }

    @Override
    public void handleShipping() {
        System.out.println("Shipping handled for paid order.");
    }
}

class ShippedState implements OrderState {
    @Override
    public void handlePayment() {
        System.out.println("Payment already received.");
    }

    @Override
    public void handleShipping() {
        System.out.println("Order already shipped.");
    }
}

// 上下文类
class Order {
    private OrderState currentState;

    public Order(OrderState initialState) {
        this.currentState = initialState;
    }

    public void handlePayment() {
        currentState.handlePayment();
    }

    public void handleShipping() {
        currentState.handleShipping();
    }

    public void setState(OrderState newState) {
        this.currentState = newState;
    }
}

public class StatePatternExample {
    public static void main(String[] args) {
        Order order = new Order(new PendingPaymentState());

        order.handlePayment();
        order.handleShipping();

        order.setState(new PaidState());

        order.handlePayment();
        order.handleShipping();

        order.setState(new ShippedState());

        order.handlePayment();
        order.handleShipping();
    }
}

5、枚举

对一些创建了枚举值,针对不同的枚举值有不同的操作时,枚举也可以消除if-else。个人感觉有点像策略模式或者表驱动。

  • 优化前
enum OperateTypeEnum{  
	PO(1),  
	PR(2),  
	DC_INBOUND(3),  
	DC_OUTBOUND(4);  
	  
	public final Integer code;  
	  
	OperateTypeEnum(Integer code) {  
		this.code = code;  
	}  
}

private static Long getOperator(Integer operator){  
	if (OperateTypeEnum.PO.code.equals(operator)){  
		return getPoOperator();  
	} else if (OperateTypeEnum.PR.code.equals(operator)) {  
		return getPrOperator();  
	} else if (OperateTypeEnum.DC_INBOUND.code.equals(operator)) {  
		return getDcInboundOperator();  
	} else if (OperateTypeEnum.DC_OUTBOUND.code.equals(operator)) {  
		return getDcOutboundOperator();  
	}else {  
		return null;  
	}  
}

private static Long getPoOperator(){return 1L;}  
  
private static Long getPrOperator(){return 2L;}  
  
private static Long getDcInboundOperator(){return 3L;}  
  
private static Long getDcOutboundOperator(){return 4L;}  
  
private static Long getDwInboundOperator(){return 5L;}  
  
private static Long getDwOutboundOperator(){return 6L;}

  • 优化后的代码
enum OperateTypeEnum{  
	PO(1){  
	@Override  
	protected Long getOperator() {  
			return 1L;  
		}  
	},  
	PR(2){  
	@Override  
	protected Long getOperator() {  
			return 2L;  
		}  
	},  
	DC_INBOUND(3){  
	@Override  
	protected Long getOperator() {  
			return 3L;  
		}  
	},  
	DC_OUTBOUND(4){  
	@Override  
	protected Long getOperator() {  
			return 4L;  
		}  
	};  
	  
	public final Integer code;  
	  
	OperateTypeEnum(Integer code) {  
		this.code = code;  
	}  
	  
	public static OperateTypeEnum ofCode(Integer code){  
		return Arrays.stream(OperateTypeEnum.values())
		.filter(e -> e.code.equals(code))
		.findFirst().orElseThrow(() -> new RuntimeException("出错了"));  
	}  
	  
	/**  
	* 定义一个公共方法  
	*/  
	protected abstract Long getOperator();  
}

private static Long getOperator(Integer operatorType){  
	OperateTypeEnum operateTypeEnum = OperateTypeEnum.ofCode(operatorType);  
	return operateTypeEnum.getOperator();  
}

这种方式也是我再处理一些枚举时,对应不同的处理逻辑时常用的一种方式。比如根据订单类型的不同返回类型对应的数据。当然我们枚举方法中处理逻辑时如果想用bean的话,可以当做参数传入或者直接从Spring容器中获取。

6、表驱动(Map+函数方法)

表驱动编程是一种通过查找表格而不是嵌套条件语句来实现的编程方法。可以使用数据结构(如数组、Map)来存储条件和对应的操作,这样就不必用很多的逻辑语句(if 或 case)来把它们找出来的方法。

  • 优化前代码
private static OrderInfoVO operateOrder(String orderType, OrderInfoDO orderInfo){  
	if (orderType.equals("PO")){  
		return handlePoOrder(orderInfo);  
	}else if (orderType.equals("INBOUND")){  
		return handleInboundOrder(orderInfo);  
	} else if (orderType.equals("OUTBOUND")) {  
		return handleOutboundOrder(orderInfo);  
	}  
}
  • 优化后代码
private static OrderInfoVO handlerOrder(String orderType, OrderInfoDO orderInfo){  
	Map<String, Function<OrderInfoDO, OrderInfoVO>> functionMap = Maps.newHashMap();  
	functionMap.put("PO", (orderInfo1) -> { return handlePoOrder(orderInfo1);});  
	functionMap.put("INBOUND", (orderInfo1) -> { return handleInboundOrder(orderInfo1);});  
	functionMap.put("OUTBOUND", (orderInfo1) -> { return handleOutboundOrder(orderInfo1);});  
	  
	return functionMap.get(orderType).apply(orderInfo);  
}

当然Funtion也可以根据业务需要,可以为ConsumerPredicate等。
不过我们也可以利用Spring的依赖注入,将其转换为对应的Map<String, Bean>。比如上述代码也可以这么优化:

interface IOrderHandler{  
	/**  
	* 定义统一的处理接口  
	* @param orderInfo  
	* @return  
	*/  
	OrderInfoVO handlerOrder(OrderInfoDO orderInfo);  
}  
  
@Component("PO")  
class PoOrderHandler implements IOrderHandler{  
	/**  
	* 处理Po  
	*  
	* @param orderInfo  
	* @return  
	*/  
	@Override  
	public OrderInfoVO handlerOrder(OrderInfoDO orderInfo) {  
		return null;  
	}  
}  
  
@Component("INBOUND")  
class InboundOrderHandler implements IOrderHandler{  
	/**  
	* 处理Inbound  
	*  
	* @param orderInfo  
	* @return  
	*/  
	@Override  
	public OrderInfoVO handlerOrder(OrderInfoDO orderInfo) {  
		// 具体处理逻辑  
		return null;  
	}  
}  
  
@Component("OUTBOUND")  
class InboundOrderHandler implements IOrderHandler{  
	/**  
	* 处理Outbound  
	*  
	* @param orderInfo  
	* @return  
	*/  
	@Override  
	public OrderInfoVO handlerOrder(OrderInfoDO orderInfo) {  
		return null;  
	}  
}

public class OrderSerivceImpl implements IOrderService{

	@Autowired  
	private Map<String, IOrderHandler> orderHandlerMap;

	public OrderInfoVO handleOrderInfo(String orderType, OrderInfoDO orderInfo){
		IOrderHandler orderHandler = orderHandlerMap.get(orderType);  
		return orderHandler.handlerOrder(orderInfo);
	}
}

7、策略模式+工厂模式

我们可以使用策略模式将每个条件分支抽象为一个策略类,然后在主逻辑中使用策略类来执行相应的逻辑。这种方式可以降低代码的耦合性,使得代码更加可维护和可扩展。然后再使用工厂模式定义一个策略工厂类去管理这些策略,即对外提供的都是策略工厂的方法。这种方法可以有效的去除if-else,并且代码逻辑更容易阅读维护以及扩展。
比如上例中,我们在处理不同订单类型时的handler类就是一个个的策略,我们也可以创建一个策略工厂类。

publid class OrderHandlerFactory{
	private static final Map<String, IOrderHandler> orderHandlerMap = Maps.newHashMap();  
  
static {  
	orderHandlerMap.put("PO", new PoOrderHandler());  
	orderHandlerMap.put("INBOUND", new InboundOrderHandler());  
	orderHandlerMap.put("OUTBOUND", new OutboundOrderHandler());  
}  

/**
* 获取具体处理的类
*/
public static IOrderHandler getOrderHandler(String orderType){  
return orderHandlerMap.get(orderType);  
}
}

8、规则引擎

使用规则引擎来管理条件和对应的执行逻辑。例如,Drools 是一个强大的规则引擎,它允许你定义规则并动态执行它们。再比如LiteFlow,EasyRule,都可以通过管理条件和对应的执行逻辑。可以消除if-else。规则引擎适合处理复杂的业务逻辑。通过编排条件去处理业务逻辑。后续会分享规则引擎相关的干货。有兴趣的同学可以关注公众号码农Academy

总结:

上述方案都可以达到优化if-else的效果,但是采用那种方案还是要看具体的代码逻辑以及业务处理逻辑,重要的是要评估项目的复杂性、维护性和性能需求,选择最适合项目需求的优化方案。在实际开发中,通常会根据具体情况结合多种方式来达到更好的优化效果。

本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包括Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中间件、架构设计、面试题、程序员攻略等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/308112.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

xinput1_4.dll缺失了怎么办?快速修复xinput1_4.dll文件的方法指南

在快速发展的数字时代&#xff0c;电子设备尤其是电脑成为了我们生活工作中必不可少的工具。然而&#xff0c;在使用过程中&#xff0c;我们可能会遇到各式各样的技术问题&#xff0c;其中一个常见问题是系统提示缺少 xinput1_4.dll文件。这个错误通常会在你尝试运行一个游戏或…

EF Core 在实际开发中,如何分层?

前言&#xff1a;什么是分层&#xff1f; 分层就是将 EF Core 放在单独的项目中&#xff0c;其它项目如 Asp.net core webapi 项目引用它这样的好处是解耦和项目职责的清晰划分&#xff0c;并且可以重用 EF Core 项目但是也会数据库迁移变得复杂起来 Step by step 步骤 创建一…

linux 安装 reids并使用Windows测试结果

要安装两个软件 Windows端安装下面的软件连接虚拟机中的redis Another Redis DeskTop Manager 安装和使用_another redis desktop怎么连接-CSDN博客 redis安装 查找可用版本 选择安装最多点赞的一个 安装完成后创建redis容器 docker run -t --name redis -p 6379:6379 -d r…

这6个设计小白学习网站,海量免费学习教程!

划到最后“阅读原文”——领取工具包&#xff08;超过1000工具&#xff0c;免费素材网站分享和行业报告&#xff09; Hi&#xff0c;我是胡猛夫~&#xff0c;专注于分享各类价值网站、高效工具&#xff01; ​更多资源&#xff0c;更多内容&#xff0c;欢迎交流&#xff01;公…

3d模型显示不出来?3d不显示全模型---模大狮模型网

如果3D模型在显示时不完整或者无法显示&#xff0c;可能有几个原因导致&#xff1a; 缩放问题&#xff1a;检查一下模型的缩放是否正确。有时候模型的缩放比例可能非常大或非常小&#xff0c;导致模型无法正确显示。尝试调整模型的缩放值&#xff0c;使其适合场景。 材质问题&…

主食冻干哪款好?十大放心主食冻干名单推荐

作为养猫的人&#xff0c;我们都知道每天最担心的事情就是如何为心爱的猫咪选择一款高品质的猫粮。我们都希望为猫咪提供最好的营养&#xff0c;让它们健康快乐地成长。然而&#xff0c;近期的一些事件&#xff0c;如百利猫粮生虫和VE主食冻干掰开有虫&#xff0c;让我们不得不…

Django的数据库模型的CharField字段的max_length参数与中文字符数的关系探索(参数max_length的单位是字符个数还是字节数?)

01-清理干净之前的数据库迁移信息 02-根据setting.py中的信息删除掉之前建立的数据库 03-删除之后重新创建数据库 04-models.py中创建数据库模型 from django.db import modelsclass User(models.Model):username models.CharField(max_length4)email models.EmailField(uni…

RabbitMQ安装和快速入门

文章目录 1. RabbitMQ2. 安装RabbitMQ2.1 创建shell文件2.2 编写shell文件2.3 检查rabbitmq状态2.4 设置开机自启动2.5 启动插件2.6 开放端口号2.7 创建用户2.8 登入管理页面 3. SpringBoot中集成RabbitMQ3.1 依赖安装3.2 SpringBoot配置3.3 RabbitMQ的配置类3.4 定义消费者和生…

【Cadence】sprobe的使用

实验目的&#xff1a;通过sprobe测试电路中某个节点的阻抗 这里通过sprobe测试输入阻抗&#xff0c;可以通过port来验证 设置如下&#xff1a; 说明&#xff1a;Z1代表sprobe往left看&#xff0c;Z2代表sprobe往right看 结果如下&#xff1a; 可以看到ZM1I0.Z2 顺便给出了I…

谷歌浏览器打不开设置

场景&#xff1a;谷歌浏览器页面空白&#xff0c;并且点击设置没有反应 忘记我是在哪找的解决方案了&#xff0c;先留个记号在这&#xff0c;方便下次查阅

0x53 区间DP

0x53 区间DP 到目前为止&#xff0c;我们介绍的线性DP一般从初态开始&#xff0c;沿着阶段的扩张向某个方向递推&#xff0c;直至计算出目标状态。区间DP也属于线性DP中的一种&#xff0c;它以“区间长度”作为DP的“阶段”&#xff0c;使用两个坐标&#xff08;区间的左右端点…

MongoDB查找命令find,让数据返回称心如意

业务系统接入数据库后&#xff0c;每天都有大量的数据写入数据库。面对逐日增加的数据&#xff0c;开发人员或数据分析人员&#xff0c;该如何读取数据&#xff0c;怎样设置条件&#xff0c;从数据库中查询数据&#xff1f; 本文基于mongodb的官方文档&#xff0c;整理出find命…

计算机组成原理-程序查询方式(流程图 演示过程 例题 定时查询 独占查询)

文章目录 总览IO方式简介程序查询方式程序查询方式流程图程序查询方式-例题小结 总览 IO方式简介 每次输一个字&#xff0c;就认为状态完成&#xff0c;CPU就会取走数据寄存器的内容 程序查询方式 此时模拟打印三个字符 假设此时三个字符在主存&#xff0c;CPU先从主存读一…

避免重复扣款:分布式支付系统的幂等性原理与实践

这是《百图解码支付系统设计与实现》专栏系列文章中的第&#xff08;6&#xff09;篇。 本文主要讲清楚什么是幂等性原理&#xff0c;在支付系统中的重要应用&#xff0c;业务幂等、全部幂等这些不同的幂等方案选型带来的收益和复杂度权衡&#xff0c;幂等击穿场景及可能的严重…

期末查分系统(c,链表实现)

主要功能&#xff1a; 分为三个身份: 学生:可以通过学号查询个人分数 老师&#xff1a;可以看所有学生成绩&#xff0c;单科排名&#xff08;正序&#xff0c;倒序&#xff09;&#xff0c;统计绩点&#xff0c;查看绩点排名前百分之n的学生 管理员端&#xff1a;可以创建链…

揭秘区块链的奥秘:链上智能如何诊断加密生态系统的健康状况

作者&#xff1a;shellyfootprint.network 数据源&#xff1a;Wallet Profile 在加密市场中&#xff0c;波动是家常便饭。就拿 2022 年来说&#xff0c;像 Terra、Celsius 和 FTX 这样的主要项目相继崩盘&#xff0c;搞得市场一片狼藉。这些情况往往让人措手不及&#xff0c;直…

openGauss学习笔记-192 openGauss 数据库运维-常见故障定位案例-XFS文件系统问题

文章目录 openGauss学习笔记-192 openGauss 数据库运维-常见故障定位案例-XFS文件系统问题192.1 在XFS文件系统中&#xff0c;使用du命令查询数据文件大小大于文件实际大小192.1.1 问题现象192.1.2 原因分析192.1.3 处理办法 192.2 在XFS文件系统中&#xff0c;出现文件损坏192…

工业智能网关如何保障数据通信安全

工业智能网关是组成工业物联网的重要设备&#xff0c;不仅可以起到数据交换、通信、边缘计算的功能&#xff0c;还可以发挥数据安全保障功能&#xff0c;保障工业物联网稳定、可持续。本篇就为大家简单介绍一下工业智能网关增强和确保数据通信安全的几种措施&#xff1a; 1、软…

nuxt pm2配置及使用

pm2简介 pm2是一个进程管理工具,可以用它来管理node进程&#xff0c;并查看node进程的状态&#xff0c;当然也支持性能监控&#xff0c;进程守护&#xff0c;负载均衡等功能&#xff0c;在前端和nodejs的世界中用的很多 pm2安装 安装pm2: $ npm install -g pm2查看pm2的安装…

232转Profinet实现协议互转的配置步骤

通常说的RS232是一种串口通信&#xff0c;通过发送和接收的电压变化来传递信息&#xff0c;是点对点通信&#xff0c;通信双方直接连接&#xff0c;通信速率较低。Profinet是一种以太网协议通信&#xff0c;具有传输速度快&#xff0c;支持多个设备实时应用&#xff0c;而且有更…