在处理复杂业务时, 会遇到针对不同场景做不同处理的情况, 难免会产生大量的if, else if 的代码, 不仅会影响美观, 太多的if 也会影响阅读性. 在这里提供两种依靠枚举类去消除if代码的写法供各位参考.
- 情景复现
if (StringUtils.equals(strategy,DeductStockStrategyEnum.DIRECT_UPDATE_STOCK.getCode())){
...
}else if (){
...
}else if (){
...
}
大家意会即可, 毕竟这种代码也见怪不怪了!
贴一下函数式接口的概念: 函数式接口 | 菜鸟教程
- 方法一, 函数式接口做枚举类属性
/**
* 扣减库存策略枚举
*
* @author Lynn
* @date 2022/10/20 10:32
*/
@Getter
@AllArgsConstructor
public enum DeductStockStrategyEnum {
/**
* 下单预占库存 (减库存 加锁定库存)
*/
CREATE_ORDER("createOrder",
(t, r) -> {
t.setSkuStock(t.getSkuStock() + r.getChangeStock());
t.setLockStock(t.getLockStock() - r.getChangeStock());
}),
/**
* 完成订单 (减锁定库存)
*/
COMPLETE_ORDER("completeOrder",
(t, r) -> {
t.setLockStock(t.getLockStock() - r.getChangeStock());
}),
/**
* 取消订单 (加库存 减锁定库存)
*/
CANCEL_ORDER("cancelOrder",
(t, r) -> {
t.setSkuStock(t.getSkuStock() + r.getChangeStock());
t.setLockStock(t.getLockStock() - r.getChangeStock());
}),
;
private String code;
private BiConsumer<ProductSkuDto, ProductSkuDto> deductStock;
public static BiConsumer<ProductSkuDto, ProductSkuDto> getDeductStockStrategy(String code) {
for (DeductStockStrategyEnum value : DeductStockStrategyEnum.values()) {
if (StringUtils.equals(value.getCode(), code)) {
return value.getDeductStock();
}
}
throw new BaseException(ErrorEnum.DEDUCT_STOCK_STRATEGY_ERROR);
}
}
// 根据策略处理库存
DeductStockStrategyEnum.getDeductStockStrategy(strategy).accept(ori, sku);
这里是用函数式接口做属性, 再提供一个接口, 让调用方可以通过映射, 获取对应的处理函数.
调用方一次方法调用就替代了原来的if代码.
- 方法二 将函数式接口放在接口里
/**
* @author Lynn
* @date 2022/10/20 11:54
*/
public interface EnumBiConsumer<T, R> {
/**
* 两个入参 没有出参
*
* @param t {@link T}
* @param r {@link R}
*/
void handleBiConsumer(T t, R r);
}
/**
* 扣减库存策略枚举
*
* @author Lynn
* @date 2022/10/20 10:32
*/
@Getter
@AllArgsConstructor
public enum DeductStockStrategyEnum implements EnumBiConsumer<ProductSkuDto, ProductSkuDto> {
/**
* 直接修改库存 (加/减库存)
*/
DIRECT_UPDATE_STOCK("directUpdateStock") {
@Override
public void handleBiConsumer(ProductSkuDto t, ProductSkuDto r) {
t.setSkuStock(t.getSkuStock() + r.getChangeStock());
}
},
/**
* 下单预占库存 (减库存 加锁定库存)
*/
CREATE_ORDER("createOrder") {
@Override
public void handleBiConsumer(ProductSkuDto t, ProductSkuDto r) {
t.setSkuStock(t.getSkuStock() + r.getChangeStock());
t.setLockStock(t.getLockStock() - r.getChangeStock());
}
},
/**
* 完成订单 (减锁定库存)
*/
COMPLETE_ORDER("completeOrder") {
@Override
public void handleBiConsumer(ProductSkuDto t, ProductSkuDto r) {
t.setLockStock(t.getLockStock() - r.getChangeStock());
}
},
/**
* 取消订单 (加库存 减锁定库存)
*/
CANCEL_ORDER("cancelOrder") {
@Override
public void handleBiConsumer(ProductSkuDto t, ProductSkuDto r) {
t.setSkuStock(t.getSkuStock() + r.getChangeStock());
t.setLockStock(t.getLockStock() - r.getChangeStock());
}
},
;
private String code;
public static DeductStockStrategyEnum getDeductStockStrategy(String code) {
for (DeductStockStrategyEnum value : DeductStockStrategyEnum.values()) {
if (StringUtils.equals(value.getCode(), code)) {
return value;
}
}
throw new BaseException(ErrorEnum.DEDUCT_STOCK_STRATEGY_ERROR);
}
}
// 根据策略处理库存
DeductStockStrategyEnum.getDeductStockStrategy(strategy).handleBiConsumer(ori, sku);
这里是将函数放在接口中, 所有的小枚举去实现对应的具体方法, 相较于将函数式接口用作属性, 更便于理解, 但是代码量会多一丢丢. 两种方法皆可.