看到一段代码,写的比较啰嗦就用GitHub Copilot简化了一下,简化结果很简单,复杂度从273%降低到13%(复杂度使用IDEA插件 Better Highlights )。代码行数从79行变成了29行,下面是原始代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private static boolean comparelogic(String condition, String value, String ccompare) { try { if ("0".equals(ccompare)) { if (condition.contains(value)) { return true; } else { return false; } } if ("1".equals(ccompare)) { if (!condition.contains(value)) { return true; } else { return false; } } return false;
} catch (Exception e) { return false; } }
|
第一眼看到下面代码就觉得很啰嗦:
1 2 3 4 5
| if (condition.contains(value)) { return true; } else { return false; }
|
直接写 return condition.contains(value);
即可,不要判断true时返回true,否则false。你的判断条件和返回结果一致时,直接返回判断条件即可。
除此之外本来互斥的多个if
写成了独立的,连 else if
都没使用,如果 ccompare="9"
所有 if
条件都要判断一遍才能走到最后一个符合条件的 if
。
另外这么典型的排比句,用 switch 是最合适的,经过优化后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| private static boolean comparelogic(String condition, String value, String ccompare) { try { switch (ccompare) { case "0": return condition.contains(value); case "1": return !condition.contains(value); case "2": return condition.equals(value); case "3": return !condition.equals(value); case "4": return new BigDecimal(condition).compareTo(new BigDecimal(value)) > 0; case "5": return new BigDecimal(condition).compareTo(new BigDecimal(value)) > -1; case "6": return new BigDecimal(condition).compareTo(new BigDecimal(value)) < 0; case "7": return new BigDecimal(condition).compareTo(new BigDecimal(value)) < 1; case "8": return StringUtils.isBlank(condition); case "9": return StringUtils.isNotBlank(condition); default: return false; } } catch (Exception e) { return false; } }
|
这样就足够了,当考虑 condition 可能扩展更多比较方式时,还可以考虑策略模式,如果不会变化就不要选择策略模式,几乎所有设计模式都会让类的数量爆炸式增长,这里直接给出 Copilot 的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public interface ComparatorStrategy { boolean compare(String condition, String value); }
public class ContainsComparator implements ComparatorStrategy { @Override public boolean compare(String condition, String value) { return condition.contains(value); } }
public class NotContainsComparator implements ComparatorStrategy { @Override public boolean compare(String condition, String value) { return !condition.contains(value); } }
public class CompareLogic { private static final Map<String, ComparatorStrategy> strategies = new HashMap<>();
static { strategies.put("0", new ContainsComparator()); strategies.put("1", new NotContainsComparator()); }
public static boolean comparelogic(String condition, String value, String ccompare) { ComparatorStrategy strategy = strategies.get(ccompare); if (strategy == null) { return false; } return strategy.compare(condition, value); } }
|
上面的方式消除了 if
或 switch
,但是别听信哪些为了消除 if
推荐这么做的文章,如果你有扩展 变化 的需求,这种方式很方便,附带消除了 if
。上面这个方案再配合有 IOC 注入的框架时,下面注册的代码可以去掉,做到完全不需要改动任何代码:
1 2 3 4 5 6
| static { strategies.put("0", new ContainsComparator()); strategies.put("1", new NotContainsComparator()); }
|
下面是基于Spring框架实现策略模式的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component;
import java.util.Map;
@Component public class CompareLogic { private final Map<String, ComparatorStrategy> strategies;
@Autowired public CompareLogic(ApplicationContext applicationContext) { strategies = applicationContext.getBeansOfType(ComparatorStrategy.class); }
public boolean comparelogic(String condition, String value, String ccompare) { ComparatorStrategy strategy = strategies.get(ccompare); if (strategy == null) { return false; } return strategy.compare(condition, value); } }
import org.springframework.stereotype.Component;
@Component("0") public class ContainsComparator implements ComparatorStrategy { @Override public boolean compare(String condition, String value) { return condition.contains(value); } }
import org.springframework.stereotype.Component;
@Component("1") public class NotContainsComparator implements ComparatorStrategy { @Override public boolean compare(String condition, String value) { return !condition.contains(value); } }
|
配合 IOC 使用时,像上面两个实现这样扩展就能增加新的策略,运行时扫描到就会自动注册,做到真正不修改任何代码,直接扩展新策略。
上面这个是 Copilot 给出的实现,比我常用的方式更简单,我没想到的地方是 @Component("1")
中指定的名字,使用 getBeansOfType
可以直接返回名字作为 key,实例作为 value 的 Map。我以前会增加一个接口方法来返回策略名称,然后注入 List<接口>
,遍历放到 Map 中,没想到 Copilot 给出了一个更简单的实现!又学到了。