我们平时在写代码的时候,if-else判断语句基本上必不可少,当我们的判断语句只有一两层的时候,类似下面这种,情况还好,基本上能接受;
if(condition){doSomeThing();}else{doSomeThing();}
但是当过度的使用if-else的时候,会对代码的可读性、可扩展性造成负面影响,比如类似下面这个!
if(condition1){if(condition2){if(condition3){if(condition4){if(condition5){if(condition6){doSomeThing();}}}}}}
如果判断语句越来越多,后期进行项目维护也会比较困难,对于后面接手项目的人来说,会是一个很头疼的问题了。
因此,如何去除掉代码中过多的if...else语句,反映的是程序员对软件重构、设计模式、面向对象设计、架构模式、数据结构等多方面技术的综合运用能力。
那问题来了,如何解决代码中过多的if...else语句呢?下面一起来聊聊有效的几种解决方案!
二、解决方案首先,我们编写一个简单的程序计算器,代码如下!
publicintcalculate(inta,intb,Stringoperator){intresult=Integer.MIN_VALUE;if("add".equals(operator)){result=a+b;}elseif("multiply".equals(operator)){result=a*b;}elseif("divide".equals(operator)){result=a/b;}elseif("subtract".equals(operator)){result=a-b;}returnresult;}
以上文为案例,我们一起来看看,可以对其进行改造的几种方式!
2.1、适时的return如果if里面条件判断比较单一又互斥的,我们可以在合适的位置直接return,废除掉else代码,比如将其改造成如下方式:
publicintcalculate(inta,intb,Stringoperator){if("add".equals(operator)){returna+b;}if("subtract".equals(operator)){returna-b;}if("multiply".equals(operator)){returna*b;}if("divide".equals(operator)){returna/b;}return0;}
代码瞬间是不是清晰了很多!
2.2、引入策略模式进行改造但是当if判断逻辑内容非常复杂的时候,以上的方案就有点不够优雅了,这个时候,我们可以将if判断逻辑独立成类来单独处理,操作方法如下!
首先,我们定义一个Operation接口,用于逻辑的计算publicinterfaceOperation{/***执行计算*
parama*paramb*return*/intexecute(inta,intb);}接着,分别将四个if判断逻辑独立成一个模块,来单独处理publicclassAddOperationimplementsOperation{
Overridepublicintexecute(inta,intb){returna+b;}}publicclassSubOperationimplementsOperation{
Overridepublicintexecute(inta,intb){returna-b;}}publicclassMultiOperationimplementsOperation{
Overridepublicintexecute(inta,intb){returna*b;}}publicclassDivOperationimplementsOperation{
Overridepublicintexecute(inta,intb){returna/b;}}然后,创建一个工厂类,用于处理客户端传入的参数publicclassOperatorFactory{privatestaticMapString,OperationoperationMap=newHashMap();static{//初始化实现类operationMap.put("add",newAddOperation());operationMap.put("sub",newSubOperation());operationMap.put("multi",newMultiOperation());operationMap.put("div",newDivOperation());//moreoperators}/***获取对应的目标实现类*
paramoperator*return*/publicstaticOptionalOperationgetOperation(Stringoperator){returnOptional.ofNullable(operationMap.get(operator));}}最后,在需要的地方引入方法即可!publicclassOperatorTestMain{publicstaticvoidmain(String[]args){//获取计算的目标实现类OperationtargetOperation=OperatorFactory.getOperation("add").orElseThrow(()-newIllegalArgumentException("InvalidOperator"));intresult=targetOperation.execute(1,2);System.out.println("result:"+result);}}
至此,if...else方法改造完毕!
2.3、引入规则引擎模式进行改造当方法内部的if...else越来越多的时候,我们可以通过规则引擎模式来消除这种复杂度,具体实践如下!
首先,创建一个规则标准接口Rule,并将条件判断方法进行抽象publicinterfaceRule{/***检查是否进入规则计算*
paramexpression*return*/booleanevaluate(Expressionexpression);/***执行规则计算*paramexpression*return*/intexecute(Expressionexpression);}publicclassExpression{privateIntegera;privateIntegerb;/***计算类型*/privateStringoperator;publicExpression(Integera,Integerb,Stringoperator){this.a=a;this.b=b;this.operator=operator;}}接着,根据每个规则创建不同的计算实现类,以AddRule为例
publicclassAddRuleimplementsRule{
Overridepublicbooleanevaluate(Expressionexpression){if("add".equalsIgnoreCase(expression.getOperator())){returntrue;}returnfalse;}Overridepublicintexecute(Expressionexpression){intresult=expression.getA()+expression.getB();;returnresult;}}然后,创建一个规则引擎,用于逻辑的处理publicclassRuleEngine{privatestaticListRulerules=newArrayList();static{rules.add(newAddRule());//添加其他的规则计算实现类}/***执行规则计算*
paramexpression*return*/publicintprocess(Expressionexpression){Rulerule=rules.stream().filter(r-r.evaluate(expression)).findFirst().orElseThrow(()-newIllegalArgumentException("ExpressiondoesnotmatchesanyRule"));returnrule.execute(expression);}}最后,在需要的地方引入方法即可!publicclassRuleEngineTestMain{publicstaticvoidmain(String[]args){Expressionexpression=newExpression(1,2,"add");RuleEngineengine=newRuleEngine();intresult=engine.process(expression);System.out.println("result:"+result);}}
规则引擎和策略模式,最大的不同的就是将条件逻辑判断抽象化,由具体的实现类来判断是不是满足要求,如果满足要求,就执行;否则不执行!
三、Spring集成应用可能有的同学会发出疑问,以上介绍的都是原生的处理办法,在当下处处都集成了Spring框架的项目,我们应该如何使用呢?
下面我们以上面提到的《引入策略模式进行改造》为例,如果在Spring里面,我们应该如何应用?
3.1、Spring策略模式实现介绍(方案一)首先,我们还是定义一个Command接口,用于方法的抽象和统一publicinterfaceCommand{/***命令类型*
return*/StringoperateType();/***执行*parama*paramb*return*/Integerexecute(inta,intb);}接着,编写四套不同的计算处理逻辑ComponentpublicclassAddCommandimplementsCommand{OverridepublicStringoperateType(){return"add";}OverridepublicIntegerexecute(inta,intb){returna+b;}}ComponentpublicclassSubCommandimplementsCommand{OverridepublicStringoperateType(){return"subtract";}OverridepublicIntegerexecute(inta,intb){returna-b;}}ComponentpublicclassMultiCommandimplementsCommand{OverridepublicStringoperateType(){return"multiply";}OverridepublicIntegerexecute(inta,intb){returna*b;}}ComponentpublicclassDivCommandimplementsCommand{OverridepublicStringoperateType(){return"divide";}OverridepublicIntegerexecute(inta,intb){returna/b;}}然后,编写一个类似于上文的策略处理类ComponentpublicclassCalculatorServiceimplementsApplicationContextAware{privateMapString,Command