优雅的消除if..else,这1条锦囊妙计千万别错过!!

首先来看一个demo!!

publicinterface IPay {  
    void pay();  
}  

@Service
publicclass AliaPay implements IPay {  
     @Override
     public void pay() {  
        System.out.println("===发起支付宝支付===");  
     }  
}  

@Service
publicclass WeixinPay implements IPay {  
     @Override
     public void pay() {  
         System.out.println("===发起微信支付===");  
     }  
}  
  
@Service
publicclass JingDongPay implements IPay {  
     @Override
     public void pay() {  
        System.out.println("===发起京东支付===");  
     }  
}  

@Service
publicclass PayService {  
     @Autowired
     private AliaPay aliaPay;  
     @Autowired
     private WeixinPay weixinPay;  
     @Autowired
     private JingDongPay jingDongPay;  
    
   
     public void toPay(String code) {  
         if ("alia".equals(code)) {  
             aliaPay.pay();  
         } elseif ("weixin".equals(code)) {  
              weixinPay.pay();  
         } elseif ("jingdong".equals(code)) {  
              jingDongPay.pay();  
         } else {  
              System.out.println("找不到支付方式");  
         }  
     }  
}

PayService类根据不同的code,决定调用用不同的支付类(比如:aliaPay)的pay方法进行支付。

那如果支付方式越来越多,就需要改toPay方法的代码,增加新的if...else判断!!那么代码就会显得无比冗余!!

那我们有啥好的办法可以优化这些代码呢?

我们先来看一下这个案例!!

首先定义一个注解。

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE)  
public@interface PayCode {  

     String value();    
     String name();  
}

在所有的支付类上都加上该注解

@PayCode(value = "alia", name = "支付宝支付")  
@Service
publicclass AliaPay implements IPay {  

     @Override
     public void pay() {  
         System.out.println("===发起支付宝支付===");  
     }  
}  

 
@PayCode(value = "weixin", name = "微信支付")  
@Service
publicclass WeixinPay implements IPay {  
 
     @Override
     public void pay() {  
         System.out.println("===发起微信支付===");  
     }  
} 

 
@PayCode(value = "jingdong", name = "京东支付")  
@Service
publicclass JingDongPay implements IPay {  
 
     @Override
     public void pay() {  
        System.out.println("===发起京东支付===");  
     }  
}

然后增加最关键的类:

@Service
publicclass PayService2 implements ApplicationListener<ContextRefreshedEvent> {  
 
     privatestatic Map<String, IPay> payMap = null;  
     
     @Override
     public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {  
         ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();  
         Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(PayCode.class);  
        
         if (beansWithAnnotation != null) {  
             payMap = new HashMap<>();  
             beansWithAnnotation.forEach((key, value) ->{  
                 String bizType = value.getClass().getAnnotation(PayCode.class).value();  
                 payMap.put(bizType, (IPay) value);  
             });  
         }  
     }  
    
     public void pay(String code) {  
        payMap.get(code).pay();  
     }  
}

我们获取打了PayCode注解的类,放到一个map中,map中的key就是PayCode注解中定义的value,跟code参数一致,value是支付类的实例。

这样,每次就可以每次直接通过code获取支付类实例,而不用if...else判断了。

注意:这种方式的code可以没有业务含义,可以是纯数字,只有不重复就行。

那么还有一种方法主要针对code是有业务含义的场景。

@Service
publicclass PayService3 implements ApplicationContextAware {   
     private ApplicationContext applicationContext;  
     privatestaticfinal String SUFFIX = "Pay";  

     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
        this.applicationContext = applicationContext;  
     }  

     public void toPay(String payCode) {  
         ((IPay) applicationContext.getBean(getBeanName(payCode))).pay();  
     }  

     public String getBeanName(String payCode) {  
         return payCode + SUFFIX;  
     }  
}

我们可以看到,aliaPay、weixinPay和jingDongPay,这些支付类bean的名称都是由code和后缀拼接而成!

这就要求支付类取名的时候要特别注意,前面的一段要和code保持一致。

调用的支付类的实例是直接从ApplicationContext实例中获取的,默认情况下bean是单例的,放在内存的一个map中,所以不会有性能问题。

当然实际项目开发中使用if...else判断的场景非常多,上面只是其中2种场景。

下面再列举一下其他常见的场景。

根据不同的数字返回不同的字符串
public String getMessage(int code) {  
     if (code == 1) {  
        return"成功";  
     } elseif (code == -1) {  
        return"失败";  
     } elseif (code == -2) {  
        return"网络超时";  
     } elseif (code == -3) {  
        return"参数错误";  
     }  
     thrownew RuntimeException("code错误");  
}

其实,这种判断没有必要,用一个枚举就可以搞定。

publicenum MessageEnum {  
     SUCCESS(1, "成功"),  
     FAIL(-1, "失败"),  
     TIME_OUT(-2, "网络超时"),  
     PARAM_ERROR(-3, "参数错误");  

     privateint code;  
     private String message;  

     MessageEnum(int code, String message) {  
         this.code = code;  
         this.message = message;  
     }  
   
     public int getCode() {  
        returnthis.code;  
     }  

     public String getMessage() {  
        returnthis.message;  
     }  
  
     public static MessageEnum getMessageEnum(int code) {  
        return Arrays.stream(MessageEnum.values()).filter(x -> x.code == code).findFirst().orElse(null);  
     }  
}

再把调用方法稍微调整一下

public String getMessage(int code) {  
     MessageEnum messageEnum = MessageEnum.getMessageEnum(code);  
     return messageEnum.getMessage();  
}

完美!!!

当然,还有很多其他的场景可以优化if...else,我再这里就不一一介绍了,感兴趣的朋友可以给我留言,一起探讨和研究一下。

最后说一句(求关注!)

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。

关注公众号:woniuxgg,在公众号中回复:笔记  就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值