你还在用if-else吗?鲍勃大叔提出改进意见!


if/else/switch语句的泛滥是软件系统中的常见问题。它们在许多地方被复制的事实是有问题的。
几天前,有人在推特上发了一个问题,询问以下哪个PHP片段更好,或者是否有更好的方法。

我的建议是:将if / else放入一个工厂对象中,这个工厂是为每个变量创建一个多态对象。在“ main”中创建工厂并将其传递到您的应用中。这将确保if / else链仅出现一次。

if/else/switch语句存在一个更严重的问题。这是依赖结构。

此类陈述倾向于将案例指向外部,指向较低级别的模块。这通常意味着包含的模块if/else/switch将依赖于那些较低级别的模块的源代码。这些if/else/switch语句变成了依赖磁铁,这些磁铁吸引了大范围的系统源代码,从而将系统绑定到了紧密的整体式体系结构中,而没有灵活的组件结构。
够糟糕的。我们不喜欢从高级模块到低级模块的依赖关系。他们阻止了我们创建由可独立部署的组件组成的体系结构的愿望。
解决此问题的方法是打破那些对较低级别模块的向外依赖。这可以通过简单的多态来完成。

在上图中,您可以看到使用基类接口的高级模块,该接口多态地部署到低级详细信息。稍加思考,您就应该能够看出这与行为在本质上是相同的,if/else/switch但是有所不同。在那些高级策略模块调用基类接口之前,必须先确定要遵循哪种情况。
现在,仅查看依赖关系的方向。从高级模块到低级模块不再有任何传递源代码依赖性。我们可以轻松地创建一个将它们分开的组件边界。我们甚至可以独立于低层模块部署高层模块。这构成了令人愉悦的灵活体系结构。
要考虑的另一点是if/else/switch和的多态实现都使用表查找来完成其工作。在if/else表的情况下,表查找是过程性的。在switch大多数情况下,编译器会建立一个小的查询表。在多态调度的情况下,向量表被内置到基类接口中。因此,这三个都具有非常相似的运行时和内存特征。一个并不比另一个快得多。
那么,决策从何而来呢?当创建基类的实例时做出决定。希望创作发生在一个很好的安全地方,如main。通常,我们使用简单的工厂类来管理它。


在上图中,您可以看到高级模块使用基类来完成其工作。曾经依赖于一条语句的每个业务规则,有其自己的特定方法来在基类中进行调用。当业务规则调用该方法时,它将部署到适当的低级模块。低级模块由Factory创建。
再次注意依赖关系的方向。看到那条红线吗?这是一个方便的组件边界。所有依赖项都指向较高级别的模块。
高级模块调用传递表示决策的某种令牌的make(x)方法。请谨慎使用该令牌x。请勿尝试使其成为需要在红线上方进行声明的enum 或任何其他内容。整数或字符串是令牌x更好的选择。它可能不是类型安全的。实际上,它不是类型安全的。但是,它将允许您保留体系结构的组件结构。
您可能会担心另一件事。该基类需要为曾经依赖于if/else/switch决策的每个业务规则提供一种方法。随着更多这些业务规则的出现,您将不得不向基类添加更多方法。而且由于许多业务规则已经依赖于基类,因此即使他们不关心任何更改,也必须重新编译/重新部署它们。
有很多方法可以解决该问题。我可以继续用这个博客写另外2,000个单词,或者描述它们。为避免这种情况,我建议您查找“接口隔离原理”和“非循环访问者”模式。

 
相关:
鲍勃大爷:将if/else中每个条件变为逻辑并列互拆而不依赖执行顺序。
 
幽默:当你的代码中有多个嵌套if-else语句时

banq 2006年的文章:你还在用if else吗?https://www.jdon.com/artichect/ifelse.htm