探讨并解决在 Java 开发中 if else 过多的问题

概述

程序中 if else 的判断本质是 条件和执行

  • 匹配:就是指条件判断,返回的值为 true, 比如:if(true), if("a".equals("b"))
  • 执行:就是指符合条件判断后需要执行的代码

基于对 条件和执行 的认识,可以从结构上对程序进行改造,可以将 匹配 和 执行的部分拆开。

关键点

  1. 条件和执行逻辑上分离,有助于代码解耦
  2. 条件可以通过 list 和 map 封装,借助 list 的遍历和 map 的 hash 来找到需要执行的代码
  3. 执行的部分一般实现了函数式接口
  4. 条件和执行在 spring boot 项目中可以通过 @Configuration 进行初始化

具体做法

  1. 通过 list 结构
  2. 通过 map 结构
  3. 在 spring boot 项目中的应用

通过 list 结构

  1. KeyValuePair 类,封装了 条件和执行逻辑
1
2
3
4
5
6
7
8
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class KeyValuePair<Condition, Execution> {
private Condition mCondition;
private Execution mExecution;
}
  1. 订单实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class OrderEntity {
private Long id;
private Long userId;
private OrderTypeEnum orderType;
private Date orderDate;
private BigDecimal orderAmount;
}

public static enum OrderTypeEnum {
online,
offline;
}
  1. 通过 list 来封装整个订单处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Test
public void test_order_list() {
List<KeyValuePair<OrderTypeEnum, Consumer<OrderEntity>>> orderHandlerList =
new ArrayList<KeyValuePair<OrderTypeEnum, Consumer<OrderEntity>>>() {{

add(KeyValuePair.<OrderTypeEnum, Consumer<OrderEntity>>builder()
.mCondition(OrderTypeEnum.online)
.mExecution(order -> {
System.out.println(
String.format("处理线上订单, 订单信息:%s", order.toString()));
})
.build());

add(KeyValuePair.<OrderTypeEnum, Consumer<OrderEntity>>builder()
.mCondition(OrderTypeEnum.offline)
.mExecution(order -> {
System.out.println(String.format("处理线下订单, 订单信息:%s",
order.toString()));
})
.build());
}};


final OrderEntity orderEntity = OrderEntity.builder()
.orderType(OrderTypeEnum.offline)
.orderAmount(BigDecimal.valueOf(23))
.build();

orderHandlerList.stream()
.filter(entity -> Objects.equals(entity.getMCondition(), orderEntity.getOrderType()))
.map(KeyValuePair::getMExecution)
.findAny()
.ifPresent(con -> con.accept(orderEntity));

}

通过 map 结构

  1. 通过 map 来封装订单处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Test
public void test_order_map() {
Map<OrderTypeEnum, Consumer<OrderEntity>> orderHandlerMap =
new HashMap<OrderTypeEnum, Consumer<OrderEntity>>() {{

put(OrderTypeEnum.online, order -> {
System.out.println(String.format("处理线上订单, 订单信息:%s",
order.toString()));
});

put(OrderTypeEnum.offline, order -> {
System.out.println(String.format("处理线下订单, 订单信息:%s",
order.toString()));
});
}};

OrderEntity orderEntity = OrderEntity.builder()
.orderType(OrderTypeEnum.online)
.orderAmount(BigDecimal.valueOf(23))
.build();

orderHandlerMap.get(orderEntity.getOrderType()).accept(orderEntity);

orderEntity = OrderEntity.builder()
.orderType(OrderTypeEnum.offline)
.orderAmount(BigDecimal.valueOf(23))
.build();

orderHandlerMap.get(orderEntity.getOrderType()).accept(orderEntity);
}

在 spring boot 项目中的应用

  1. 通过 @Configuration 类将订单处理逻辑 map 注册到 ioc 容器中,具体如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.ckjava.test.config;

import com.ckjava.test.entity.OrderEntity;
import com.ckjava.test.entity.OrderTypeEnum;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
* Function: 订单处理器
*
* @author 执剑
* @date 2022/4/5
*/
@Configuration
public class OrderHandlerConfig {

@Bean
public Map<OrderTypeEnum, Function<OrderEntity, String>> orderHandlerMap() {
return new HashMap<OrderTypeEnum, Function<OrderEntity, String>>() {{

put(OrderTypeEnum.online, order -> {
return String.format("处理线上订单, 订单信息:%s",
order.toString());
});

put(OrderTypeEnum.offline, order -> {
return String.format("处理线下订单, 订单信息:%s",
order.toString());
});
}};
}
}
  1. 在 controller 中的使用如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.ckjava.test.web;

import com.ckjava.test.entity.OrderEntity;
import com.ckjava.test.entity.OrderTypeEnum;
import com.ckjava.xutils.Constants;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Map;
import java.util.function.Function;

@Api
@RestController
@RequestMapping(value = "/order", produces = "application/json;charset=utf-8")
public class OrderController implements Constants {

@Resource
private Map<OrderTypeEnum, Function<OrderEntity, String>> orderHandlerMap;

@PostMapping(value = "/handler")
public String orderHandler(@RequestBody OrderEntity orderEntity) {
return orderHandlerMap.get(orderEntity.getOrderType()).apply(orderEntity);
}
}

打赏

  • 微信

  • 支付宝