【问题标题】:Many else if statements in the code [closed]代码中的许多其他 if 语句 [关闭]
【发布时间】:2018-10-09 18:57:18
【问题描述】:

我想问一下,基于下面的布尔条件,有许多 else if 语句是否是一种好方法?

public void borrowItem() throws IOException {

    boolean ableToBorrow = isUserAbleToBorrow(cardID);
    boolean isDemand = checkDemand(title, authorNumber);
    boolean userExists = checkIfUserExists(cardID);


    if(ableToBorrow && isDemand && userExists) {

           //lots of code....

    }else if(!ableToBorrow && isDemand && userExists) {
        System.out.println("User limit  exceeded");
    }else if(!ableToBorrow && !isDemand && userExists) {
        System.out.println("User limit  exceeded and no book demand");
    }else if(ableToBorrow && !isDemand && userExists) {
        System.out.println("No book demand");
    }else if(ableToBorrow && !isDemand && !userExists) {
        System.out.println("No book demand and user does not exists");
    }else if(ableToBorrow && isDemand && !userExists) {
        System.out.println("Unrecognized user!");
    }

}

这是一个好方法还是在java中有更好的想法来做到这一点?

【问题讨论】:

  • 什么是“好”?只要你的代码可读,多个 if-else 没有错。
  • 您可以以分层方式对其进行分段,例如if (ableToBorrow)if (isDemand) 内部以及if (userExists) 内部。可能有更好的方法,我现在看不到。
  • 不,不好。很难阅读代码,也很难理解每个条件的作用以及是否涵盖了真/假的所有可能组合。
  • @Maroun 啊,不。根本没有。冗长的 if-else 链(几乎)从来都不是一件好事。尽可能避免它们。
  • @GhostCat 除非你是研究人员 ;) 说真的,有时过度 OOPing 会导致代码错误。如果是一堆 4-5 的 if-else,我可以轻松忍受。

标签: java if-statement conditional sentence


【解决方案1】:

这是一种非常糟糕的风格:难以阅读和理解,当你被要求增强/改变行为时很容易搞砸。请注意,此类代码也非常难以测试 - 因为您需要确保涵盖在这种方法中流可能采用的所有路径。

这类事情的典型答案是使用多态性,比如有一个定义某些接口的基类,以及每个以不同方式实现接口的特定子类。

从这个意义上说:您的代码明显违反了Tell Don't Ask:您从某处编码查询某些状态,然后对此做出决定。相反,您创建类/对象并告诉它们做正确的事情(再次强调:这就是多态性的作用)。

【讨论】:

    【解决方案2】:

    它的方式没有问题,但如果您希望代码更简洁,还有其他选择。如果我稍微改变你的错误信息,我可以这样写:

    if(ableToBorrow && isDemand && userExists) {
       //lots of code....
    } else {
      String errorMsg = "";
      if (!ableToBorrow) errorMsg += "User limit  exceeded - ";
      if (!isDemand) errorMsg += "No book demand - ";
      if (!userExists) errorMsg += "Unrecognized user!"
      System.out.println(errorMsg);
    } 
    

    还可以选择将布尔值捆绑为单个整数值。这会混淆您的代码正在做什么,除非您想创建一个枚举来跟踪整数值的含义,否则我个人不会使用它;

    int status = 4*(ableToBorrow?1:0)+2*(isDemand?1:0)+(userExists?1:0);
    switch(status){
      case 7:  //lots of code....
        break;
      case 3:  System.out.println("User limit  exceeded");
        break;
      //etc...
    }
    

    【讨论】:

    • int status ... 在 C/驱动程序代码中是(将是)不错的技巧,但在这里很难接受
    【解决方案3】:

    我同意GhostCat wrote 的说法。这太程序化了。实现多态性的一种方法(在这种情况下可能是最好的方法)是decorator pattern

    定义你的界面:

    public interface User {
        void borrowItem(String item);
        String cardId();
    }
    

    创建基础实现:

    public final class SimpleUser implements User {
        private final String cardId;
        public SimpleUser(final String cardId) {
            this.cardId = cardId;
        }
        @Override
        public void borrowItem(final String item) {
            // Borrowing logic.
        }
        @Override
        public String cardId() {
            return cardId;
        }
    }
    

    然后为您需要的每个验证添加装饰器。例如。检查用户是否存在:

    public final class ExistingUser implements User {
        private final User origin;
        public ExistingUser(final User origin) {
            this.origin = origin;
        }
        @Override
        public void borrowItem(final String item) {
            if (!exists(cardId())) {
                throw new IllegalStateException("Unrecognized user!");
            }
            origin.borrowItem(item);
        }
        @Override
        public String cardId() {
            return origin.cardId();
        }
        private boolean exists(String cardId) {
            // Check if exists...
        }
    }
    

    并将它们结合起来。这样,当您需要一个额外的验证时,您可以添加一个额外的装饰器。使用ifs,病例数将呈几何级增长。

    new ExistingUser(
        new DemandAwareUser(
            new SafelyBorrowingUser(
                new SimpleUser(cardId)
            )
        )
    ).borrowItem(item);
    

    【讨论】:

    • 我会试试的,谢谢:)
    猜你喜欢
    • 2015-09-28
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多