当前位置: 首页 > 后端技术 > Java

重构if语句的多种方法

时间:2023-04-01 13:35:45 Java

1。前言if/else语句在项目开发初期一般比较简单,然后随着时间的推移和业务量的增加,if/else语句会越来越长。下面详细分析如何重构if/else。2.案例研究我们经常会遇到业务逻辑涉及到很多条件,并且每个条件需要不同的处理,我们使用Calculator类作为演示示例。有一种方法将两个数字和一个运算符作为输入,并根据运算返回相应的结果: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;}我们也可以使用switch语句来实现:publicintcalculateUsingSwitch(inta,intb,Stringoperator){开关(运算符){案例“添加”:结果=a+b;break;//其他情况}returnresult;}在实际项目开发中,if语句可能会变得更大更复杂,此时switch语句就不太适合了,下面会介绍一个更好的模式来解决if/其他问题。3.重构3.1工厂类if/else在各个分支进行类似的操作。我们通过工厂方法返回指定类型的对象,根据对象的具体行为进行操作。让我们用一个应用方法定义一个Operation接口:publicinterfaceOperation{intapply(inta,intb);}这个方法接受两个数字作为输入并返回结果。让我们定义一个用于执行加法的类:publicclassAdditionimplementsOperation{@Overridepublicintapply(inta,intb){returna+b;我们现在将实现一个工厂类,它根据给定的运算符返回一个Operation实例来执行操作:publicclassOperatorFactory{staticMapoperationMap=newHashMap<>();static{operationMap.put(“添加”,新加法());operationMap.put("除法",newDivision());//更多运算符}publicstaticOptionalgetOperation(Stringoperator){returnOptional.ofNullable(operationMap.get(operator));}}现在,在Calculator类中,我们可以查询工厂以获取相关操作:publicintcalculateUsingFactory(inta,intb,Stringoperator){OperationtargetOperation=OperatorFactory.getOperation(operator).orElseThrow(()->newIllegalArgumentException("InvalidOperator"));returntargetOperation.apply(a,b);}在这个例子中,我们看到了如何将责任委托给工厂类提供的松散耦合对象,但有可能嵌套的if语句只是转移到工厂类,并且我们可以维护一个Objectrepository,可以查询它来快速查找,所以设计了OperatorFactory中的operationMap对象。3.2使用Enumeration除了使用Map,我们还可以使用Enum来标记具体的业务逻辑。之后,我们可以在嵌套的if语句或switchcase语句中使用它们。或者,我们也可以将它们用作对象的工厂,并制定策略来执行相关的业务逻辑。这减少了嵌套的if语句和委托到单个枚举值的数量。让我们看看如何实现它。首先,我们需要定义我们的枚举:publicenumOperator{ADD,MULTIPLY,SUBTRACT,DIVIDE}我们可以选择使用枚举值作为嵌套if语句或switchcase中的不同条件。下面将介绍一种将逻辑委托给Enum本身的替代方法。首先为每个Enum值定义方法并进行计算。例如:ADD{@Overridepublicintapply(inta,intb){returna+b;}},//otheroperatorspublicabstractintapply(inta,intb);那么在Calculator类中,我们可以定义一个执行运算的方法:ADD{@Overridepublicintapply(inta,intb){returna+b;}},//otheroperatorspublicabstractintapply(int一个,诠释b);现在,我们可以使用运算符。valueOf()方法将字符串值转换为运算符以调用此方法:@TestpublicvoidwhenCalculateUsingEnumOperator_thenReturnCorrectResult(){Calculatorcalculator=newCalculator();intresult=calculator.calculate(3,4,Operator.valueOf("ADD"));assertEquals(7,result);}3.3命令模式命令模式是解决嵌套if语句的另一种方式,我们可以设计一个Calculator#calculate方法来接受可执行的命令。我们首先定义我们的Command接口:publicinterfaceCommand{Integerexecute();}接下来,让我们实现一个AddCommand:publicclassAddCommandimplementsCommand{//InstancevariablespublicAddCommand(inta,intb){this.a=a;this.b=b;}@OverridepublicIntegerexecute(){returna+b;}}最后,让我们在Calculator中引入一个接受并执行命令的新方法:publicintcalculate(Commandcommand){returncommand.execute();}接下来,我们可以通过实例化AddCommand并将其发送到Calculator#calculate方法来调用计算:@TestpublicvoidwhenCalculateUsingCommand_thenReturnCorrectResult(){Calculatorcalculator=newCalculator();intresult=calculator.calculate(newAddCommand(3,7));assertEquals(10,result);}3.4规则引擎当我们最终编写大量嵌套的if语句时,每个条件都描述了一个必须被评估以处理正确逻辑的业务规则。规则引擎从主代码中消除了这种复杂性。让我们通过设计一个简单的RuleEngine来演示,该RuleEngine通过一组规则处理Expression并返回所选规则的结果。首先,我们将定义一个Rule接口:publicinterfaceRule{booleanevaluate(Expressionexpression);ResultgetResult();}其次,让我们实现一个RuleEngine:publicclassRuleEngine{privatestaticListrules=newArrayList<>();static{rules.add(newAddRule());}publicResultprocess(Expressionexpression){Rulerule=rules.stream().filter(r->r.evaluate(expression)).findFirst().orElseThrow(()->newIllegalArgumentException("表达式不匹配任何规则"));返回规则.getResult();}}RuleEngine接受一个Expression对象并返回结果。现在,让我们将Expression类设计为包含两个Integer对象的一组运算符:公共类AddRule实现规则{@Overridepublicbooleanevaluate(Expressionexpression){booleanevalResult=false;if(expression.getOperator()==Operator.ADD){this.result=expression.getX()+expression.getY();评估结果=真;}returnevalResult;}}我们现在将使用表达式调用RuleEngine:@TestpublicvoidwhenNumbersGivenToRuleEngine_thenReturnCorrectResult(){Expressionexpression=newExpression(5,5,Operator.ADD);RuleEngineengine=newRuleEngine();Resultresult=engine.process(expression);assertNotNull(result);assertEquals(10,result.getValue());}4结语通过上面的方法我们重构了if/else语句,将不仅仅局限于switch/casef的方式,不同的方式来简化还探讨了使用有效的设计模式来复杂代码和替换嵌套if语句。