一、场景:
1 2 3 4 5 6 7 8 9 10 11
| if (很复杂的条件A){ }else if (很复杂的条件B){ }else if (很复杂的条件C){ }else if (很复杂的条件D){ }else if (很复杂的条件E){ }
|
如上述代码,工作中经常遇到这种场景,导致代码的可读性较差。对后续代码的扩展维护来说,是巨大的灾难。
以上代码有以下几点问题:
后续增加任何功能,都需要在原来耦合的代码里添加代码,有可能会影响原有功能。
没有做到开闭原则,一段良好的代码需要做到对扩展开发,对修改关闭。
校验的逻辑都在一个类中,导致这个类中的代码很多,从而影响了代码的可读性、可维护性。
if-else条件判断很难懂,无法判断某个条件中的校验到底是校验哪种校验类型,每次查看这段代码都要研究好久。
二、解决:
使用策略工厂模式来解决以上问题,把每种校验的方式封装起来,然后通过策略工厂模式来路由下发,把冗长的代码解耦出来,形成了一套框架,并且保证了代码的扩展性。
2.1 创建策略工厂类
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
| public class CheckStrategyFactory { private final Map<CheckStrategySelector, InterfaceCheck> strategyRegistry = new HashMap<>();
@Autowired public CheckStrategyFactory(ACheck aCheck, BCompare bCompare, CCheck cCheck, DCheck dCheck, ASelector aSelector,BSelector bSelector,CSelector cSelector,DSelector dSelector) {
strategyRegistry.put(aSelector, aCheck); strategyRegistry.put(bSelector, bCompare); strategyRegistry.put(cSelector, cCheck); strategyRegistry.put(dSelector, dCheck); }
public InterfaceCheck getStrategy(MatcheA ma, MatcheB mb) {
for (Map.Entry<CheckStrategySelector, InterfaceCheck> entry : strategyRegistry.entrySet()) { if (entry.getKey().matches(ma, mb)) { return entry.getValue(); } }
return null; } }
|
2.2 创建策略选择接口和校验接口
创建2个接口,一个策略选择接口CheckStrategySelector,一个校验接口InterfaceCheck。
1 2 3
| public interface CheckStrategySelector { boolean matches(MatcheA ma, MatcheB mb); }
|
1 2 3
| public interface InterfaceCheck { CheckOutputModel check(CheckA ca, CheckB cb); }
|
2.3 实现策略选择接口和校验接口
再创建4个策略类和4个校验类分别实现策略选择接口CheckStrategySelector和校验接口InterfaceCheck。
下面仅展示一个,其他省略。
策略选择实现类
1 2 3 4 5 6 7
| public class ASelector implements CheckStrategySelector { @Override public boolean matches(MatcheA ma, MatcheB mb) { return ma && mb; } }
|
校验实现类
1 2 3 4 5 6 7
| @Service("aCheck") public class ACheck implements InterfaceCheck { @Override public CheckOutputModel check(CheckA ca, CheckB cb) { } }
|
2.4 改造if判断
最后“场景”章节中的if判断语句块,改造如下
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
| @Service("commonCheckHandler") public class CommonCheckHandler implements CheckHandler{ private final CheckStrategyFactory factory;
public CommonCheckHandler(CheckStrategyFactory factory) { this.factory = factory; }
@Override public CheckOutputModel doHandle(A paramA, B paramB, C paramC) throws Exception { CheckOutputModel result = new CheckOutputModel(); MatcheA ma = paramA.getMatcheA(); MatcheB mb = paramB.getMatcheB();
InterfaceCheck interfaceCheckStrategy = factory.getStrategy(ma, mb); if(interfaceCheckStrategy != null){ return interfaceCheckStrategy.check(paramC.getCheckA(), paramC.getCheckB()); } else { result.setSuccess(false); result.setErrorCode("未找到对应的校验策略"); return result; } } }
|
以上通过策略工厂模式把那段代码拆成了多个文件,通过策略工厂模式把冗长的if-else代码给分解了。
重构之后,创建了工厂类,由工厂类中的策略判断逻辑来决定是哪一种策略类型,在运行时动态确定使用哪种策略,最终路由到对应的校验方法里。
重构后的代码符合了开闭原则,添加新策略的时候,最小化、集中化代码改动、减少引入bug的风险。
重构后的代码解耦了之前代码的复杂度,解耦了策略的定义、创建和使用,控制代码复杂度,让每个部分的代码不至于太复杂、代码量过多。现在每个类的代码基本上在一显示屏就能展示完成。
增加了代码的可读性和可维护性。
三、总结
不是所有if-else分支都是烂代码,只要if-else分支不复杂,代码不多,这并没有问题,只要遵循KISS原则,怎么简单怎么来,就是最好的设计。
一旦if-else分支很多,且每个分支都包含很多复杂的逻辑判断,这个时候就可以考虑是不是通过策略模式可以更清晰的梳理代码,使得代码维护性更强。
1 2 3 4 5 6
| 本文为个人知识学习,非原创!非作者!如本博客有侵权行为,请与我联系。 摘录以下文章,内容根据个人需求有所删减,尊重知识产出,尊重作者知识劳动成果。
作者:阿里云开发者 汪峰(蔚风) 链接:https://mp.weixin.qq.com/s/tg4vTL6_TI-tnxaMyVLhsA 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
|