在实际业务开发中,常常面临多个条件判断的情况,如果不加思索就写代码,很容易出现一堆if else 的代码,导致代码逻辑不清晰,可阅读性很差,笔者现在改造中的一个历史遗留项目,大片大片的if else,给后来人带来很大的理解成本。过多的if else ,这是很明显的坏代码的味道,这时就应该考虑自己的设计是否合理,有没有更好的表达方式了。二、if else 重构技巧
1.适当提前return这是判断条件取反的做法,代码在逻辑表达上会更清晰,先看看下面这段demo示例代码:
1/** 2 * 判断用户余额是否足够取现 3 * @param userId 4 * @param withdrawAmount 取现金额 5 * @return 6 */ 7 public Boolean checkBanlance(Long userId,BigDecimal withdrawAmount) { 8 9 User user = userDao.getUser(userId); 10 if (user != null) { 11 if (withdrawAmount.compareTo(user.getBalance()) <= 0) { 12 return Boolean.TRUE; 13 } else { 14 return false; 15 } 16 } 17 return false; 18 }这段就可以通过if条件判断提前return来避免if嵌套的问题,如果user对象为空直接return false,如下:
1public Boolean checkBanlance2(Long userId,BigDecimal withdrawAmount) { 2 User user = userDao.getUser(userId); 3 if (user == null) { 4 return Boolean.FALSE; 5 } 6 if (withdrawAmount.compareTo(user.getBalance()) <= 0) { 7 return Boolean.TRUE; 8 } else { 9 return false; 10 } 11 return false; 12 }2.用布尔表达式来代替上面的函数返回的结果是一个Boolean,那我们可以用一个布尔表达式来表示,如下:
1public Boolean checkBanlance3(Long userId,BigDecimal withdrawAmount) { 2 3 User user = userDao.getUser(userId); 4 if (user == null) { 5 return Boolean.FALSE; 6 } 7 return withdrawAmount.compareTo(user.getBalance()) <= 0; 8 }checkBanlance3 相比checkBanlance2的代码又可以简化了许多!
3.Map结合反射来代替if else以一个获取手机号的demo代码来说明这种用法,代码如下:
1public class UserMobile { 2 3 public String getMobile1() { 4 5 return "114774440"; 6 } 7 8 public String getMobile2() { 9 10 return "1448720444"; 11 } 12 13 public String getMobile3() { 14 15 return "1447191222"; 16 } 17 18 public String getMobiel(String name) { 19 20 if (StringUtils.equals(name, "xiaoming")) { 21 return this.getMobile1(); 22 } else if (StringUtils.equals(name, "xiaohua")) { 23 return this.getMobile2(); 24 } else if (StringUtils.equals(name, "xiaozhang")) { 25 return this.getMobile3(); 26 } 27 return ""; 28 } 29}getMobiel方法根据姓名来获取手机号,不同的人返回不同的手机号,按照现在的写法,if else 很容易被滥用,尤其是要新增其他用户的时候。这时候我们可以考虑使用map来代替if else,思路是:将name作为key,将getMobile1/getMobile2/getMobile3这三个方法名作为value,放在map中,然后根据参数name,获取对应的方法名,然后使用反射来调用相关的方法。示例代码如下:
1public class UserMobile { 2 3 static Map<String, String> map = new HashMap<String, String>(); 4 static { 5 map.put("xiaoming", "getMobile1"); 6 map.put("xiaohua", "getMobile2"); 7 map.put("xiaozhang", "getMobile3"); 8 } 9 10 public String getMobile1() { 11 12 return "114774440"; 13 } 14 15 public String getMobile2() { 16 17 return "1448720444"; 18 } 19 20 public String getMobile3() { 21 22 return "1447191222"; 23 } 24 25 26 public String getMobiel(String name) throws Exception { 27 28 String methodName = map.get(name); 29 if (StringUtils.isEmpty(methodName)) { 30 return ""; 31 } 32 Method method = this.getClass().getMethod(methodName,new Class[]{}); 33 String mobile = (String) method.invoke(this); 34 return mobile; 35 } 36 37 public static void main(String[] args) throws Exception { 38 39 UserMobile userMobile = new UserMobile(); 40 String mobile = userMobile.getMobiel("xiaoming"); 41 System.out.println("mobile:"+mobile); 42 } 43}这种用法一般多用于需要选择不同的执行方法时可以尝试使用! 除了这种处理方式外,还可以使用枚举。
4.用枚举来代替if else
1public enum UserInfo { 2 3 XIAOMING("xiaoming"){ 4 @Override 5 public String getUserMobile() { 6 return "13652222"; 7 } 8 }, 9 XIAOHUA("xiaohua"){ 10 @Override 11 public String getUserMobile() { 12 return "12555555896"; 13 } 14 }, 15 XIAOZHANG("xiaozhang") { 16 @Override 17 public String getUserMobile() { 18 return "12555555896"; 19 } 20 }; 21 22 private String userName; 23 24 private String mobile; 25 26 UserInfo(String userName) { 27 this.userName = userName; 28 } 29 30 public String getUserName() { 31 return userName; 32 } 33 34 public void setUserName(String userName) { 35 this.userName = userName; 36 } 37 38 public void setMobile(String mobile) { 39 this.mobile = mobile; 40 } 41 42 public String getMobile(String name) { 43 44 for (UserInfo userInfo : UserInfo.values()) { 45 if (StringUtils.equals(name,userInfo.getUserName())) { 46 userInfo.getUserMobile(); 47 } 48 } 49 return ""; 50 } 51 52 public abstract String getUserMobile(); 53}5.应用多态来代替if else
1public class RestaurantService { 2 3 public void provideService(String worker) { 4 if (StringUtils.equals(worker,"waiter")) { 5 System.out.println("拿瓶红酒"); 6 } else if (StringUtils.equals(worker,"cook")){ 7 System.out.println("做一盘番茄鸡蛋"); 8 } else if (StringUtils.equals(worker,"cleaner")) { 9 System.out.println("打扫一下卫生"); 10 } else { 11 System.out.println("sorry,没有此项服务"); 12 } 13 } 14}这是以餐厅的服务场景为例一个demo,这段代码写法,很容易引发if else的滥用,如果再增加一些服务,继续这种用法,只能不断的if else,那代码的可阅读性极差,且逻辑繁杂。
我们可以考虑使用多态,将不同的服务定义为一个子类,将每种服务封装到子类中。
1public interface RestService { 2 3 void provideService(); 4} 5 6 7public class Cleaner implements RestService { 8 9 @Override 10 public void provideService() { 11 System.out.println("打扫一下卫生"); 12 } 13} 14 15public class Cook implements RestService { 16 17 @Override 18 public void provideService() { 19 System.out.println("做一盘番茄鸡蛋"); 20 } 21} 22 23public class Waiter implements RestService { 24 25 @Override 26 public void provideService() { 27 System.out.println("拿瓶红酒"); 28 } 29} 30 31public class RestaurantService { 32 33 static Map<String, RestService> registerService = new HashMap<>(); 34 static { 35 registerService.put("waiter", new Waiter()); 36 registerService.put("cook", new Cook()); 37 registerService.put("cleaner", new Cleaner()); 38 } 39 40 public void getService(String name) { 41 42 RestService restService = registerService.get(name); 43 44 if (restService==null) { 45 System.out.println("sorry,没有此项服务"); 46 return; 47 } 48 restService.provideService(); 49 } 50 51 52 public static void main(String[] args) { 53 54 RestaurantService factory = new RestaurantService(); 55 factory.getService("cleaner"); 56 } 57}将waiter、cook、cleaner这三个角色分别定义三个子类,通过接口来调用需要用到的服务。RestaurantService类中,将三个服务注册到map中,根据key来获取对应的服务,这也是用map来代替if else的一种用法。
注意,本文探讨的是过多的if else的重构技巧,不要为了重构而重构。
更多内容欢迎关注个人微信公众号,一起成长!
