处理--烦人的if/else

过去的,未来的
2022-01-29 / 0 评论 / 1 点赞 / 658 阅读 / 8,037 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-01-29,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

背景

有一个支付的功能,他包含可以选择支付渠道(微信、支付宝)、支付方式(余额、银行卡),如下图:
image.png

基本做法

 public static void main(String[] args) {
        Integer type=0;
        Integer mode=0;
        if (type== 0){//微信
            if (mode ==0){//余额
                //todo
            }else if (mode == 1){//银行卡
                //todo
            }
        }else if (type== 1){//支付宝
            if (mode ==0){//余额
                //todo
            }else if (mode == 1){//银行卡
                //todo
            }
        }
    }

上面的if/esle看着是不是很烦人,如果业务复杂,这样写出来的代码很难维护和扩展。

换个思路

1、我们先定义一些基本的类

支付渠道--枚举:

public enum PayTypeEnum {

    WX("微信",0),

    ALIPAY("支付宝",1);

    private String name;
    private Integer value;

    PayTypeEnum(String name,Integer value){
        this.name=name;
        this.value=value;
    }


    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }
}

支付方式--枚举:

public enum PayModeEnum {

    BALANCE("余额",0),

    BANK_CARD("银行卡",1);

    private String name;
    private Integer value;

    PayModeEnum(String name,Integer value){
        this.name=name;
        this.value=value;
    }


    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }
}

常量:


public class CommConstant {

    public static String ORDER_ID="orderId";

    /***
     * 支付渠道的key
     */
    public static String TYPE="type";

    /**
     * 支付方式的key
     */
    public static String MODE="mode";

}

异常类

public class ThirdErrorException extends RuntimeException{

    public ThirdErrorException() {
    }

    public ThirdErrorException(String message) {
        super(message);
    }

    public ThirdErrorException(String message, Throwable cause) {
        super(message, cause);
    }
}


public class ParamErrorException extends RuntimeException{


    public ParamErrorException() {
    }

    public ParamErrorException(String message) {
        super(message);
    }

    public ParamErrorException(String message, Throwable cause) {
        super(message, cause);
    }

}

public class BusinessException extends RuntimeException{


    public BusinessException() {
    }

    public BusinessException(String message) {
        super(message);
    }

    public BusinessException(String message, Throwable cause) {
        super(message, cause);
    }

}
2、我们接下来定义支付
public interface PayExecutor {

    /**
     * 支付渠道
     * @return
     */
    PayTypeEnum support();

    /**
     * 执行支付
     * @param param
     */
    void  doPayExecutor(Map<String,Object> param);

}
3、定义支付方式
public interface PayProcessor {

    /**
     * 支付方式
     * @return
     */
    PayModeEnum supportMode();

    /**
     * 支付渠道
     * @return
     */
    PayTypeEnum supportType();


    /**
     * 支付检查参数
     * @param param
     */
    void checkParam(Map<String,Object> param);

    /**
     * 执行支付
     * @param param
     */
    void payProcessor(Map<String,Object> param);
}
4、抽象一个支付方式,用来扩展使用
public abstract class AbstractPayProcessor  implements PayProcessor{

    /**
     * 这里可以写一些前置的校验或者通用的处理逻辑
     * @param param
     * @throws ParamErrorException
     * @throws ThirdErrorException
     */
    void preProcessor(Map<String,Object> param) throws ParamErrorException, ThirdErrorException {
        String orderId = MapUtils.getString(param, CommConstant.ORDER_ID);
        if (StringUtils.isBlank(orderId)){
            throw new ParamErrorException("订单id不能为空!");
        }
    }
}
5、定义一个抽象的支付,扩展使用
public abstract class AbstractApyExecutor implements PayExecutor {

    /**
     * 选择支付方式
     * @param payProcessorList
     * @param map
     * @return
     */
    public PayProcessor select(List<PayProcessor> payProcessorList,Map<String, Object> map){
        Integer mode = MapUtils.getInteger(map, CommConstant.MODE);
        Integer type = MapUtils.getInteger(map, CommConstant.TYPE);
        Optional<PayProcessor> first = payProcessorList.stream()
                .filter(t -> t.supportMode().getValue().equals(mode) && t.supportType().getValue().equals(type) ).
                collect(Collectors.toList()).stream().findFirst();
        if (first.isPresent()){
            return first.get();
        }
        return null;
    }
}
6、下面我们就可实现每种支付渠道的获取

1)微信

@Service
public class WXPayExecutor extends AbstractApyExecutor{


    @Autowired
    private List<PayProcessor> payProcessorList;

    @Override
    public PayTypeEnum support() {
        return PayTypeEnum.WX;
    }

    /**
     * 支付过程
     * @param param
     */
    @Override
    public void doPayExecutor(Map<String, Object> param) {
        PayProcessor payProcessor= select(payProcessorList,param);
        payProcessor.checkParam(param);
        payProcessor.payProcessor(param);
        System.out.println("WXPayExecutor");
    }
}

2)支付宝

@Service
@Slf4j
public class ALIPayExecutor extends AbstractApyExecutor{
    @Autowired
    private List<PayProcessor> payProcessorList;

    @Override
    public PayTypeEnum support() {
        return PayTypeEnum.ALIPAY;
    }

    @Override
    public void doPayExecutor(Map<String, Object> param) {
        PayProcessor payProcessor= select(payProcessorList,param);
        payProcessor.checkParam(param);
        payProcessor.payProcessor(param);

    }
}
7、下面我们就可以编写具体的每种支付方式的实现了

1)微信余额

@Service
public class WXBalancePayProcessor extends AbstractPayProcessor {


    @Override
    public PayModeEnum supportMode() {
        return PayModeEnum.BALANCE;
    }

    @Override
    public PayTypeEnum supportType() {
        return PayTypeEnum.WX;
    }

    @Override
    public void checkParam(Map<String, Object> param) {
        preProcessor(param);
        System.out.println("WXBalancePayProcessor checkParam*****");
    }

    @Override
    public void payProcessor(Map<String, Object> param) {
        System.out.println("WXBalancePayProcessor payProcessor*****");

    }

    @Override
    void preProcessor(Map<String, Object> param) throws ParamErrorException, ThirdErrorException {
       System.out.println("**********");
    }
}

2)微信的银行卡

@Service
public class WXBankCardPayProcessor extends AbstractPayProcessor {


    @Override
    public PayModeEnum supportMode() {
        return PayModeEnum.BANK_CARD;
    }

    @Override
    public PayTypeEnum supportType() {
        return PayTypeEnum.WX;
    }

    @Override
    public void checkParam(Map<String, Object> param) {
        preProcessor(param);
        System.out.println("WXBankCardPayProcessor checkParam*****");

    }

    @Override
    public void payProcessor(Map<String, Object> param) {

        System.out.println("WXBankCardPayProcessor payProcessor*****");


    }
}

3)支付宝的余额

@Service
public class ALIBalancePayProcessor extends AbstractPayProcessor {


    @Override
    public PayModeEnum supportMode() {
        return PayModeEnum.BALANCE;
    }

    @Override
    public PayTypeEnum supportType() {
        return PayTypeEnum.ALIPAY;
    }

    @Override
    public void checkParam(Map<String, Object> param) {
        preProcessor(param);
        System.out.println("ALIBalancePayProcessor checkParam*****");
    }

    @Override
    public void payProcessor(Map<String, Object> param) {
        System.out.println("ALIBalancePayProcessor payProcessor*****");

    }
}

4)支付宝的银行卡

@Service
public class ALIBankCardPayProcessor extends AbstractPayProcessor {


    @Override
    public PayModeEnum supportMode() {
        return PayModeEnum.BANK_CARD;
    }

    @Override
    public PayTypeEnum supportType() {
        return PayTypeEnum.ALIPAY;
    }

    @Override
    public void checkParam(Map<String, Object> param) {
        preProcessor(param);
        System.out.println("ALIBankCardPayProcessor checkParam*****");

    }

    @Override
    public void payProcessor(Map<String, Object> param) {
        System.out.println("ALIBankCardPayProcessor payProcessor*****");


    }
}
8、实现一个抽象的支付service
public abstract class AbstractApyService {

    /**
     * 选择器,选择支付渠道
     * @param payExecutorList
     * @param map
     * @return
     */
    public PayExecutor select(List<PayExecutor> payExecutorList,Map<String, Object> map){
        Integer type = MapUtils.getInteger(map, CommConstant.TYPE);
        Optional<PayExecutor> first = payExecutorList.stream().filter(t -> t.support().getValue().equals(type)).
                collect(Collectors.toList()).stream().findFirst();
        if (first.isPresent()){
            return first.get();
        }
        return null;
    }
}
9、编写一个支付service
@Service
@Slf4j
public class PayService extends AbstractApyService{

    @Autowired
    private List<PayExecutor> payExecutorList;

    /**
     * 支付
     * @param map
     */
    public void pay(Map<String, Object> map){
        try {
            PayExecutor select = select(payExecutorList,map);
            select.doPayExecutor(map);
            //通过不同的异常处理不同的业务情况
        }catch (ParamErrorException e){//参数异样
            //todo
            throw new BusinessException(e.getMessage());
        }catch (ThirdErrorException e){//调用第三方异常
            //todo
            throw new BusinessException(e.getMessage());
        }
    }
}
10、我们再写一个controller测试下
@RestController
@Slf4j
public class PayController {

    @Autowired
    private PayService payService;

    @RequestMapping("/pay")
    public ResultWrapper pay(@RequestBody  Map<String,Object> map){
        log.info("pay param={}", JSON.toJSONString(map));
        try {
            payService.pay(map);
            return ResultWrapper.getSuccessReturn(map);
        }catch (BusinessException e){
            log.error("pay BusinessException error={}",e.getMessage());
            return  ResultWrapper.getFailure(e.getMessage());
        }catch (Exception e){
            log.error("pay error",e);
            return  ResultWrapper.getFailure("操作失败,请检查后重试!");
        }
    }

}
11、测试

1)微信余额
image.png

后台打印:
image.png

2)微信的银行卡
image.png

后台打印:
image.png

3)支付宝的余额
image.png
后台打印:
image.png

总结

以上就是我们这次对if/else的改造,看上去代码变多了一些,但是可扩展性和可维护性变强了,并且创建了多个异常类,可以通过不同的异常,处理不同的响应结果,我们要根据业务场景选择合适的处理方式,如果业务简单,可以继续用简单的if/else实现,简单又方便,业务复杂多变,建议使用扩展性和维护性好的。

源码链接:https://gitee.com/fengpt/fengpt-if-esle.git

1

评论区