重复校验有效性的多方案重试代码存在异味?是否需重构?
当然要重构!这绝对是需要优化的代码异味
你这段代码里重复的if(!isValid(result))检查是典型的重复代码异味——不仅看起来冗余,后续维护起来也麻烦:比如要加个planE,你得再复制粘贴一遍判断逻辑,万一哪天改了isValid的判断规则,还得挨个改所有的if语句,很容易漏。
给你几个实用的重构方案,根据你的场景选就行:
方案1:轻量遍历(最适合简单场景)
把所有计划方法放到一个可迭代的集合里,遍历执行直到找到有效结果,代码一下子就清爽了:
import java.util.Arrays; import java.util.List; import java.util.function.Supplier; // 把所有plan包装成Supplier(无参返回String的函数式接口) List<Supplier<String>> plans = Arrays.asList( this::planA, this::planB, this::planC, this::planD ); // 流式遍历,找到第一个有效的结果 String result = plans.stream() .map(Supplier::get) .filter(this::isValid) .findFirst() .orElse(null); // 所有plan都无效时返回null,也可以换成你的默认值 return result;
这个方案的好处:
- 完全消除了重复的判断逻辑
- 新增plan只需要往列表里加一行,符合开闭原则
- 逻辑一目了然,别人看代码瞬间就能懂是在依次尝试各个方案
如果你的项目还在用Java 8之前的版本,没法用Stream,那就用普通循环:
String result = null; Supplier<String>[] plans = new Supplier[]{this::planA, this::planB, this::planC, this::planD}; for (Supplier<String> plan : plans) { result = plan.get(); if (isValid(result)) { break; } } return result;
方案2:责任链模式(适合复杂场景)
如果你的各个plan后续可能需要添加不同的逻辑(比如不同的参数、前置检查),那责任链模式会更灵活。把每个plan封装成一个处理器,处理器自己负责执行和判断,不行就交给下一个:
// 定义处理器接口 interface PlanHandler { String handle(); PlanHandler setNext(PlanHandler next); } // 实现PlanA处理器 class PlanAHandler implements PlanHandler { private PlanHandler next; @Override public String handle() { String result = planA(); if (isValid(result)) { return result; } return next != null ? next.handle() : null; } @Override public PlanHandler setNext(PlanHandler next) { this.next = next; return this; } } // 同理实现PlanBHandler、PlanCHandler、PlanDHandler... // 组装责任链并执行 PlanHandler handlerChain = new PlanAHandler() .setNext(new PlanBHandler()) .setNext(new PlanCHandler()) .setNext(new PlanDHandler()); String result = handlerChain.handle(); return result;
这个方案的好处:
- 每个plan的逻辑完全解耦,各自负责自己的执行和判断
- 可以灵活调整处理器的顺序,或者动态添加/移除处理器
- 后续扩展复杂逻辑时不会污染主流程代码
总结
不管选哪种方案,核心都是消除重复代码、提高可维护性。原来的代码重复了多次相同的判断逻辑,属于典型的代码异味,重构之后不仅代码更干净,后续维护也会省心很多。
内容的提问来源于stack exchange,提问作者Matteo_B
相关产品推荐
相关产品推荐

