if(condition){ //doSomething }else{ } return;优化后如下:
if(!condition){ return; }二、能省则省,规避最后的else
public Result addUser() { if (StrUtil.equals(userStatus, "online")) { return doStep1(); } else { return doStep2(); } // else 后面没有其他业务时,可省略最后的else,使代码简洁 }优化后的代码:
public Result addUser() { if (StrUtil.equals(userStatus, "online")) { return doStep1(); } return doStep2(); }当然这里面要注意的点是,一定要确认是最后的else,并没有其他的业务逻辑。
public Result addUser() { return StrUtil.equals(userStatus, "online")) ?doStep1() : doStep2(); }一个方法一行代码搞定。
if (user == null) { throw new Exception("未查询到用户信息"); } if (user != null) { update(user); // 执行方法调用 }代码优化后:
Optional.ofNullable(user).orElseThrow(() -> new Exception("未查询到用户信息")); Optional.ofNullable(user).ifPresent(user -> update(user));隐式调用相当优雅。
public void addUser(User user) { // 1.非空校验 if (StrUtil.isBlank(user.getUsername())) { throw new RuntimeException("用户名为空!"); } if (StrUtil.isBlank(user.getPassword())) { throw new RuntimeException("密码为空!"); } ... // 2.格式校验 if (!ValidUtil.isIdCardNo(user.getIdCardNo())) { throw new RuntimeException("身份证号格式错误!"); } if (!ValidUtil.isEmail(user.getEmail())) { throw new RuntimeException("手机号格式错误!"); } if (!ValidUtil.isEmail(user.getEmail())) { throw new RuntimeException("邮箱格式错误!"); } ... // 3.要四素认证校验 if(!doFourStampVerify(User user)){ throw new RuntimeException("四要素认证失败!"); } }此处可能还有很多其他的省略的场景。所以单个文件中的If else可能比想象中多的多。那么我们如何用责任链模式进行优化呢?
/** * 处理器链接口 */ public interface UserChainHandler { void handler(User user); }剩下不同的场景校验只要去实现这个接口就可以了,不过需要定义好顺序
@Component @Order(1) // 指定注入顺序 public class UserParamNullValidChainHandler implements UserChainHandler { @Override public void handler(User user) { // 1.非空校验 if (StrUtil.isBlank(user.getUsername())) { throw new RuntimeException("用户名为空!"); } if (StrUtil.isBlank(user.getPassword())) { throw new RuntimeException("密码为空!"); } } @Component @Order(1) // 指定注入顺序 public class UserParamNullValidChainHandler implements UserChainHandler { @Override public void handler(User user) { // 1.非空校验 if (StrUtil.isBlank(user.getUsername())) { throw new RuntimeException("用户名为空!"); } ... } /** * 格式校验处理器 */ @Component @Order(2) // 指定注入顺序 public class UserParamFormatValidChainHandler implements UserChainHandler { @Override public void handler(User user) { // 2.格式校验 if (!ValidUtil.isIdCardNo(user.getIdCardNo())) { throw new RuntimeException("身份证号格式错误!"); } ... } /** * 四要素处理器 */ @Component @Order(3) // 指定注入顺序 public class FourElementVerifyChainHandler implements UserChainHandler { @Override public void handler(User user) { // 2.格式校验 if (!doFourStampVerify(User user)) { throw new RuntimeException("四要素认证失败!"); } } //进行组装 @Component @RequiredArgsConstructor public class UserChainContext { private final List<UserChainHandler> userChainHandlerList; // 自动注入责任链处理器 /** * 责任链组件执行 * * @param requestParam 请求参数 */ public void handler(User user) { // 此处根据 Ordered 实际值进行排序处理 userChainHandlerList.forEach(x -> x.handler(user)); } }最终咱们的原来的add方法进行这样调用就好了
public void addUser(User user) { // 执行责任链 userChainContext.handler(user); }第二种,合理使用策略模式+工厂模式。
public Result calcPrice(CalcPriceParam calcPriceParam){ //判断对应的计算价格的场景 Integer type = judgeType(calcPriceParam); //根据场景调用不同的方法 ,建议更好的编码习惯是把type改成枚举类型哈~ if(type == 1){ return calcPriceForTypeOne(); } if(type == 2){ return calcPriceForTypeTwo(); } if(type == 3){ return calcPriceForTypeThree(); } ..... if(typr == 10){ return calcPriceForTypeTen(); } }显而易见随着会员价格场景套餐越来越多,我们的if也会越来越多。
public interface Strategy { Result calcPrice(CalcPriceParam calcPriceParam); int getBizType(); } @Service public Class firstStragy implement Strategy { Result calcPrice(CalcPriceParam calcPriceParam) { .... return result; } int getBizType() { return 1; } } public Class secondStragy implement Strategy { Result calcPrice(CalcPriceParam calcPriceParam) { .... return result; } int getBizType() { return 2; } } @Service public class StrategyContext{ Map<Integer,CalcPriceInterface> strategyContextMap = new HashMap<>(); //注入对应的策略类 @Autowired Strategy[] strategys; @PostConstruct public void setStrategyContextMap(){ for(Stragegy stragegy:strategys){ strategyContextMap.put(stragegy.getCode,stragegy); } } //根据场景调用不同的方法 public Result calcPrice(CalcPriceParam calcPriceParam){ Integer type = judgeType(calcPriceParam); CalcPriceInterface calcPriceInstance = strategyContextMap.get(type); return calcPriceInstance.calcPrice(calcPriceParam); } }这样一来,咱们上面的第一个方法中的If else的实现将会变得很简单,如下:
@Autowired StrategyContext strategyContext; public Result calcPrice(CalcPriceParam calcPriceParam){ strategyContext.calcPrice(calcPriceParam); }这样即使新增新的计算模式,我们只需去实现Strategy接口并且重写里面两个方法即可完成后续业务的拓展。代码优雅简单,可维护性强。
Map<String, Function<?> action> actionMap = new HashMap<>(); action.put("type1",() -> {calcPriceForTypeOne()}); action.put("type2",() -> {calcPriceForTypeTwo()}); action.put("type3",() -> {calcPriceForTypeThree()}); ... // 使用 actionMap.get(action).apply();当然如果想要再优化得好一些的话,可以进行接口抽取,然后进行实现,在此不展开,留下给小伙伴们思考一下。
if(status.equals(1)){ return "订单未支付"; }else if(status.equals(2)){ return "订单已支付" }else if(status.equals(3)){ return "订单已发货" } .....优化后
@Getter @AllArgsConstructor public enum OrderStatusEnum { UN_PAID("1","订单未支付"), PAIDED("2","订单已支付"), SENDED("3","订单已发货"), .....; private String status; private String statusDes; static OrderStatusEnum of(String status) { for (OrderStatusEnum statusEnum : OrderStatusEnum.values()) { if (statusEnum.getStatus().equals(status)) { return statusEnum; } } return null; } } String orderStatusDes = OrderStatusEnum.of(orderStatus).getStatusDes();等等还有其他一些,由于这些优化个人认为是没法标准化的优化原则,不同的业务场景都不同,所以在此,老猫不将其放在通用优化中,认为这个是其他优化方式。
3.虽然经过好几轮研发之手,有的研发害怕改出业务问题,所以选择继续堆屎山。