干掉Switch 语句

162 阅读2分钟

昨天 CR 代码,被吐槽了👇的代码,自己也看不下去:

    // 福利配置校验
    configs.forEach(x -> doValidate(x, welfareSendCreateBO));

这段又臭又长的Switch

/**
     * 发送校验配置信息
     *
     * @param configDO           
     * @param welfareSendCreateBO 校验参数
     */
    private void doValidate(WelfareConfigDO configDO, WelfareSendCreateBO welfareSendCreateBO) {
        switch (configDO.getCode()) {
            case WelfareConfigConstants.CURRENCIES:
                checkCurrencies(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.AMOUNT_MAX: 
                checkAmountMax(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.AMOUNT_MIN:
                checkAmountMin(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.CURRENCY_MIN:
                checkCurrencyMin(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.CURRENCY_MAX:
                checkCurrencyMax(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.CURRENCY_MAX_NUM:
                checkCurrencyMaxNum(configDO.getValue(), welfareSendCreateBO.getSendNum());
                break;
            case WelfareConfigConstants.CURRENCY_MIN_NUM:
                checkCurrencyMinNum(configDO.getValue(), welfareSendCreateBO.getSendNum());
                break;
            case WelfareConfigConstants.FLOATING_LOWERBOUND:
                checkFloatingLowerBound(configDO.getValue(), welfareSendCreateBO);
                break;
            case WelfareConfigConstants.FLOATING_UPPERBOUND:
                checkFloatingUpperBound(configDO.getValue(), welfareSendCreateBO);
                break;
            default:
                break;
        }
    }

功能是为了校验参数,不同的参数有不同的规则,可是规则越长,分支越多,代码丑死,被diss的心悦臣服,写的太赶都没有考虑代码的扩展性。

早上起来重构了下代码,采用策略模式接口的形式进行调用。

  1. 抽象一个配置项的处理器
  • 处理配置项
  • 获取配置项处理器名称 (唯一且约定的)
/**
 * 发送福利参数校验
 * <p>
 * Created by Reeta on 2019-07-12
 */
public interface IConfigHandler {

    /**
     * 发送福利配置校验,校验值是否满足配置值
     *
     * @param configValue 配置值
     * @param checkValue  校验值
     */
    void handleTheConfig(String configValue, WelfareSendCreateBO checkValue);

    /**
     * 返回校验配置项的名称
     *
     * @return WelfareConfigConstants
     */
    String getConfigHandleName();
}
  1. 不同的配置项去实现处理逻辑,就列举了两个,不一一列举了
/**
 * 校验币种是否在配置值中
 * <p>
 * Created by Reeta on 2019-07-12
 */
@Component
public class CurrenciesConfigHandler implements IConfigHandler {


    @Override
    public void handleTheConfig(String value, WelfareSendCreateBO currency) {
        boolean anyMatch = Arrays.stream(value.split(",")).anyMatch(s -> s.equals(currency.getCurrency()));
        AssertUtil.assertTrue(anyMatch, "Invalid currency to send welfare", WelfareErrorCode.BIZ_ERROR);
    }

    @Override
    public String getConfigHandleName() {
        return WelfareConfigConstants.CURRENCIES;
    }
}
/**
 * 单个福利发送数量上限
 * <p>
 * Created by Reeta on 2019-07-13
 */
@Component
public class CurrencyMaxConfigHandler implements IConfigHandler {
    @Override
    public void handleTheConfig(String configValue, WelfareSendCreateBO checkValue) {
        int to = checkValue.getSendAmount().divide(new BigDecimal(checkValue.getSendNum()), 20, BigDecimal.ROUND_DOWN)
                .compareTo(new BigDecimal(configValue));
        AssertUtil.assertTrue(to < 1, WelfareErrorCode.WELFARE_CURRENCY_MAX);

    }

    @Override
    public String getConfigHandleName() {
        return WelfareConfigConstants.CURRENCY_MAX;
    }


}
  1. 使用简单工厂模式 将配置项的处理器放入List 容器内,通过配置项的唯一code值获取不同的处理器
/**
 * 福利配置处理器工厂类
 * <p>
 * Created by Reeta on 2019-07-13
 */
@Component
public class ConfigHandlerFactory {

    @Autowired
    List<IConfigHandler> configHandlers;

    /**
     * 通过配置值返回配置处理器
     *
     * @param code 配置的唯一code
     * @return 配置处理器
     */
    public IConfigHandler getConfigHandler(String code) {
        AssertUtil.assertNotBlank(code, "ConfigHandler name is empty!", CommonErrorCode.INNER_ERROR);
        AssertUtil.assertNotNull(configHandlers, "ConfigHandler is null", CommonErrorCode.INNER_ERROR);
        for (IConfigHandler configHandler : configHandlers) {
            if (code.equalsIgnoreCase(configHandler.getConfigHandleName())) {
                return configHandler;
            }
        }
        throw new BaseException("No ConfigHandler was found for name: " + code, CommonErrorCode.SYSTEM_EXCEPTION);
    }
}
  1. 最后 干掉Switch 语句 :) ~~~~
 // 福利配置校验
        configs.forEach(x -> {
            AssertUtil.assertNotBlank(x.getValue(),
                    x.getCode() + "cannot be empty", CommonErrorCode.SYSTEM_EXCEPTION);
            configHandlerFactory.getConfigHandler(x.getCode()).handleTheConfig(x.getValue(), welfareSendCreateBO);
        });