首页 > 其他分享 >代码整洁之道(一)之优化if-else的8种方案

代码整洁之道(一)之优化if-else的8种方案

时间:2024-01-30 11:23:56浏览次数:28  
标签:return void else 之道 static println public 整洁

我们日常开发的项目中,如果代码中存在大量的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、中间件、架构设计、面试题、程序员攻略等

标签:return,void,else,之道,static,println,public,整洁
From: https://www.cnblogs.com/coderacademy/p/17994553

相关文章

  • 2024.1.18《程序员的修炼之道:从小工到专家》阅读笔记1
    《程序员的修炼之道:从小工到专家》是一本经典的计算机编程领域的书籍,由AndrewHunt和DavidThomas合著。这本书以富有启发性的方式,向读者展示了成为一名优秀程序员的道路。本书以通俗易懂的语言,深入浅出地解释了编程领域的一些基本概念和原则。作者通过生动的案例和具体的实践经验......
  • 2024.1.22《程序员的修炼之道:从小工到专家》阅读笔记2
    《程序员的修炼之道:从小工到专家》强调了“软件工匠”的概念,即通过不断的学习和实践,不断提升自己的技能和素养,最终成为一名优秀的程序员。作者提出了“不断学习、不断改进”的观念,鼓励读者在编程之路上不断追求卓越。这让我深受鼓舞,也让我意识到编程领域是一个永无止境的学习之路,......
  • <<程序员修炼之道:从小工到专家>>读后感
    《程序员修炼之道:从小工到专家》是一本深刻揭示编程世界本质的著作。在阅读后,我深感这不仅仅是一本关于编程技术的书籍,更是一本关于职业发展、软件设计和人生态度的指南。首先,书中强调的代码质量和可读性给我留下深刻印象。作者强调写出高质量、易读懂的代码是每位程序员的责任。......
  • 《程序员修炼之道:从小工到专家》(三)
    首先,我被书中所强调的“实效性”所吸引。实效性并非仅仅关乎技术,更是一种思维方式。书中强调解决问题的实际方法,而非盲目地追求理论。这让我开始更注重解决问题的方法,而不仅仅是关注技术的新潮与炫丽。“不要重复自己”(DRY)的原则给予我对代码质量的新认识。作者强调代码的可读性......
  • 《程序员修炼之道:从小工到专家》(二)
    它不仅是一本关于编程技术的书籍,更是一本关于如何成为卓越软件开发者的实用指南。在阅读过程中,我获得了许多有关职业发展、编程哲学和团队协作的宝贵经验。首先,书中强调的实效性理念给我带来了全新的思考方式。不追求理论的空谈,而是注重解决问题的实际手段。作者鼓励我们要时刻保......
  • 《程序员的修炼之道:从小工到专家》的阅读笔记
    《程序员的修炼之道:从小工到专家》是由AndrewHunt和DavidThomas合著的一本经典之作,以实用的方式探讨了成为卓越程序员的路径。以下是我对这本书的阅读笔记:首先,书中强调了“注重实践”和“不断学习”的重要性。程序员并非仅仅需要理论知识,更需要通过实践不断提升自己。书中提到......
  • C#中Dictionary与ConcurrentDictionary解锁多线程操作安全之道
     使用C#中的Dictionary与ConcurrentDictionary进行多线程操作在C#中,Dictionary是一个常见的字典类型,但它不是线程安全的。为了在多线程环境中确保安全的操作,我们可以使用ConcurrentDictionary,这是一个专门设计用于多线程场景的线程安全字典。1.使用Dictionary进行非线程安......
  • 泛互联网行业A/B测试全解析:产品优化的创新之道
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群近期,火山引擎数智平台举办了“超话数据:企业产品优化分享”的活动。火山引擎产品解决方案专家从企业应用的视角,分享了A/B实验在产品全用户生命周期的体验优化和案例。在用户拉新环节,企业可以......
  • 数据探索之道:查询Web API数据中的JSON字符串列
    前言在当今数据驱动的时代,对数据进行探索和分析变得愈发关键。WebAPI作为广泛应用的数据源,提供了丰富的信息和资源。然而,面对包含JSON字符串列的WebAPI数据时,我们常常遇到一个挑战:如何高效灵活地处理和查询这些数据?这个问题在数据探索和提取过程中频繁出现。因此小编今天以葡萄......
  • 你有被if-else支配过吗?看完这篇文章,你就知道该怎么做
    在日常工作中,如果让你碰到一大堆if-else嵌套的代码,你会怎么做?背景最近在给之前负责的项目做CR的时候,在项目代码中发现有大量的if-else判断语句,阅读起来非常的折磨人而且也不利于后期的维护扩展,比较容易出问题。当时我直接气血上涌,差点昏过去。缓过几分钟之后,把写这段代码的......