【问题标题】:Better way to handle n number of if-else if in java在java中处理n个if-else if的更好方法
【发布时间】:2017-07-15 05:27:28
【问题描述】:

我想知道是否有更好的方法来处理 n no。 Java 中的 if/else-if 块。

我有一种情况,我需要根据 n 号打印不同的值。 if/else-if/conditions 块,如

if(p==1 && q==r)
  System.out.println("Condition 1");
else if(r==p && q==9)
  System.out.println("Condition 2");
else if(z==1 && s==r)
  System.out.println("Condition 3");
else if(p==1 || x==r && y==7)
  System.out.println("Condition 4");
else if(q==z && y==r || p==4)
  System.out.println("Condition 5");
else if(x==z && r==5 || z==30)
  System.out.println("Condition 6");
else if(s==1 || q==x)
  System.out.println("Condition 7");
else if(r==14 || q==r++ || z==y)
  System.out.println("Condition 8");
else if(q==18 && s==r || p==90)
  System.out.println("Condition 9");
else if(y==19 || q==89)
  System.out.println("Condition 10");
...

有没有其他方法来处理它,而不是放置多个 if/else if 语句,以便以后如果有任何新条件出现,它会很容易处理。

【问题讨论】:

  • 很难给出一般性的答案。也许您想更多地讲述您遇到此要求的情况,并且有人可以从更高的角度提出建议。
  • 这种情况的一个常见例子是推销员问题,他需要根据天气、距离、时间、业务优先级、否等多种因素决定每天去哪个城市。要会见的目标客户数量、个人优先事项、第二天计划的访问等。
  • 还是有点模糊。对于推销员,我想我会使用一个数据结构来描述每个可能的城市(例如距离、目标客户数量、天气敏感性、上次访问日期和优先客户列表)。然后是一个方法,甚至是一个策略类,从数据中挑选出最好的城市并将其返回给我。
  • 我很感激接受 ;-)

标签: java if-statement optimization conditional-statements


【解决方案1】:

真正的答案是:不要那样做。

在良好的 OO 设计中,您解决这个问题的方式非常不同;例如通过使用多态性。您实际上希望避免拥有许多不同的信息来源,然后据此做出决定。

在你的情况下;例如,我会考虑 FSM 和 state pattern

我的意思是:您的代码显示了解决问题的某种“方法”。只要您保持这种方法不变,您只是在谈论寻找以“最不丑陋”的方式表达您的解决方案的方法。

相反,您应该退后一步,寻找可以用“非常漂亮”的方式表达的方法。

因此:您的问题没有“简单”的直接答案。您必须退后一步,仔细查看您想要满足的要求;然后设计一个更好的“更多面向对象”的解决方案。

这里最简单的事情是:您可以从声明一个枚举开始,例如:

public enum Condition {
  A, B, C, ...

然后你会有一些工厂方法隐藏所有这些语句;喜欢:

Condition currentCondition = determineCondition(p, q, r, z);
switch(currentCondition) {
  case A:

含义:您至少希望将这些知识“集中”到某个地方以避免代码重复。但又一次;这就像在一辆生锈的旧车上涂上新颜色一样。它暂时有所帮助,但并没有真正改善。

关于您的 cmets:是的,switch 仅比 if elses 稍微“更好”。但正如你所说:你不能有太多机会,所以至少你想要有确切的一个确定状态的代码。

但最后:我认为你在错误的层面上接近这个。您可能正在处理某种复杂的业务逻辑;你想像这样在低层次上解决这个问题。但是没有您在这样的级别上所做的任何事情都不会带来强大的、长期可维护的解决方案。可能真正的解决方案是退后一步,考虑使用某种workflow engine

【讨论】:

  • 不错的选择,但是当您仍然需要切换时,您的关注点分离仍然不完美。调用代码不应该知道所有不同的选项,因为当你得到一个新选项时,你需要在这里调整代码。
  • 这就是为什么我称之为“最小的东西”;并指出它也只会在表面上增加价值;-)
  • 不错的选择,但是确定条件()方法将再次具有多个 if/else-if
  • @ernitingoel 没错。这就是为什么我要指出你要做的不仅仅是重构表面。
【解决方案2】:

您可以创建一个接受所有变量的条件(接口或超类):

public interface Condition {
    boolean isConditionMet(int p, int q, int r, int s, int x, int y, int z);
    void performAction();
}

对于每个单独的条件,您可以覆盖/实现布尔方法 isConditionMet()。

public class C1 implements Condition {
    public boolean isConditionMet(int p, int q, int r, int s, int x, int y, int z) {
        return p == 1 && q == r;
    }
    public void performAction() {
        System.out.println("Condition 1");
    }
}

然后您可以将所有条件放在一个集合中,对于您拥有的每个条件,您都可以询问:

if (condition.isConditionMet())
    condition.performAction();

现在每个 Condition 对象自身负责何时它应该采取行动,以及它应该做什么。完美的关注点分离。

【讨论】:

  • 有帮助;但距离完美。如果参数的数量发生变化……那么您必须更新所有参数。那么:unused 参数是“bad style”;很多人也认为“超过 2 个,最多 3 个”参数是“不好的风格。所以,是的,很有帮助;但只是表面上。
  • 如果我有 100 个这样的条件,我最终会有 100 个不同的类。
  • 如果你有100个条件,你将获得100个类。那是问题吗?如果是这样,您可以编写 lambda 来摆脱它,但我仍然没有看到问题。关注点是分开的,当你编写一个新的接口实现时,大部分代码都会生成,所以你很快就完成了。如果你最终有大量的 int 需要检查,并且每个需要检查的 int 总是不同的,我认为你的数据模型在其他地方有问题......
  • @ernitingoel 如果你有 100 个条件;任何以这种方式解决它的尝试迟早会导致无法维护的恐怖意大利面条代码(很快)。这就是为什么我建议你退后一步,看看other;更多 OO 方法来解决您的需求。是的,如果你有一个复杂的状态机,那么事情就会变得复杂。但是,与将它们推入巨大的 if/else 级联相比,你最好将它们很好地分离。
  • 这不是关于生成代码,而是关于维护它,没有。 n 个条件的类不是一个好的选择。 int 是这里的一个例子,我也有需要比较字符串/对象的情况。这是对现有项目的增强,我只是不能随意更改数据模型。
【解决方案3】:

投反对票的诱饵

当您说“如果出现任何新情况”时,您的意思是如果出现新情况,您愿意修改代码,还是代码必须在不被修改的情况下进行调整?如果是前者,我认为你已经做到了最好的方式。 (不过,我会在顶部添加一个if (false){},因此所有真实案例看起来都一样,从而可以轻松地重新排列它们。)如果是后者,则需要一种表驱动的方法。如果每个案例都有打印语句,性能就不是问题。如果您确实关心性能,请将最常见的情况放在首位。

如果您更关心性能,请使用 if 语句树,而不是阶梯。所以,例如,有这样的事情,所以你不会重复问同一个子问题:

if (p == 1){
    .. all the cases where p is 1
} else {
    .. all the other cases
}

可能还有其他与 OO 相关的方法来编写这个,但没有一个比这更快或更容易修改。

【讨论】:

    猜你喜欢
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2015-11-09
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多