1. 前言
项目开发初期阶段if/else语句一般比较简单,然后随着时间的推移和业务量的增加,if/else分之会越来越长。下面对如何重构if/else做出了详细分析。
2. 案例研究
我们经常遇到涉及很多条件的业务逻辑,并且每个都需要不同的处理,我们以Calculator类作为演示样例。有一个方法,它接受两个数字和一个运算符作为输入项,并根据操作返回相应结果:
1 | 复制代码public int calculate(int a, int b, String operator) { |
我们也可以使用switch语句来实现它:
1 | 复制代码public int calculateUsingSwitch(int a, int b, String operator) { |
在真正的项目开发中,if语句可能会变得更大,更复杂,这时候switch语句并不是很适合,下面将介绍更好模式来解决if/else问题。
- 重构
3.1 工厂类
if/else每个分支中执行类似的操作,我们通过工厂方法返回给指定类型的对象并基于具体对象行为执行操作。
让我们定义一个具有单个apply方法的Operation接口:
1 | 复制代码public interface Operation { |
该方法将两个数字作为输入并返回结果。让我们定义一个用于执行添加的类:
1 | 复制代码public class Addition implements Operation { |
我们现在将实现一个工厂类,它根据给定的运算符返回Operation的实例:
1 | 复制代码public class OperatorFactory { |
现在,在Calculator类中,我们可以查询工厂以获取相关操作:
1 | 复制代码public int calculateUsingFactory(int a, int b, String operator) { |
在这个例子中,我们已经看到了如何将责任委托给工厂类提供的松散耦合对象,但是有可能嵌套的if语句只是转移到了工厂类,我们可以在Map中维护一个对象存储库,可以查询该存储库以进快速查找,所以设计了OperatorFactory中的operationMap对象。
3.2 使用枚举
除了使用Map之外,我们还可以使用Enum来标记特定的业务逻辑。之后,我们可以在嵌套的if语句或switch case语句中使用它们。或者,我们也可以将它们用作对象的工厂并制定策略以执行相关的业务逻辑。这样可以减少嵌套if语句的数量并委托给单个Enum值。
让我们看看我们如何实现它。首先,我们需要定义我们的枚举:
1 | 复制代码public enum Operator { |
我们可以选择在嵌套的if语句或switch case中使用枚举值作为不同的条件,下面将介绍一种将逻辑委托给Enum本身的替代方法。
首先为每个Enum值定义方法并进行计算。例如:
1 | 复制代码ADD { |
然后在Calculator类中,我们可以定义一个可执行操作的方法:
1 | 复制代码public int calculate(int a, int b, Operator operator) { |
现在,我们可以通过使用Operator.valueOf()方法将String值转换为Operator来调用该方法:
1 | 复制代码@Test |
3.3 命令模式
命令模式是解决嵌套if语句的另一种方法,我们可以设计一个Calculator#calculate方法来接受可执行的命令。
我们首先定义我们的Command接口:
1 | 复制代码public interface Command { |
接下来,让我们实现一个AddCommand:
1 | 复制代码public class AddCommand implements Command { |
最后,让我们在Calculator中引入一个接受并执行Command的新方法:
1 | 复制代码public int calculate(Command command) { |
接下来,我们可以通过实例化AddCommand调用计算并将其发送到Calculator#calculate方法:
1 | 复制代码@Test |
3.4 规则引擎
当我们最终编写大量嵌套if语句时,每个条件都描述了一个业务规则,必须对其进行评估才能处理正确的逻辑。规则引擎从主代码中获取了这种复杂性。
让我们通过设计一个简单的RuleEngine来进行演示,该RuleEngine通过一组规则来处理Expression,并返回所选规则的结果。首先,我们将定义一个Rule接口:
1 | 复制代码public interface Rule { |
其次,让我们实现一个RuleEngine:
1 | 复制代码public class RuleEngine { |
所述RuleEngine接受一个Expression对象并返回结果。现在,让我们将Expression类设计为一组包含两个Integer对象的Operator:
1 | 复制代码public class Expression { |
最后让我们定义一个自定义的AddRule类,该类仅在指定ADD操作时进行求值:
1 | 复制代码public class AddRule implements Rule { |
我们现在将使用Expression调用RuleEngine:
1 | 复制代码@Test |
4 结论
通过上述方法我们重构if/else语句不会在仅仅局限于switch/casef方式,也探索了用不同的方法来简化复杂的代码和通过使用有效的设计模式来替换嵌套的if语句。
本文转载自: 掘金