【问题标题】:Elegant way to replace multiple if statemens to throw exceptions替换多个 if 语句以引发异常的优雅方法
【发布时间】:2019-07-04 21:27:18
【问题描述】:

我的应用程序有一个服务,其中 3 个方法执行一些验证,并根据返回的结果引发不同的异常。

  if (!check1stCondition() {
    throw new ValidationException(message1);
  }

  if (!check2ndCondition)
    throw new ValidationException(message2);

  if (!check3rdCondition)
    throw new ValidationException(message3);
}

如何重新格式化此代码以便将来可维护?将来可能会执行新的检查。

【问题讨论】:

    标签: java if-statement exception reformat


    【解决方案1】:

    您可以定义一个接口Checker 提供一个方法check 在这种情况下引发异常。您的代码可以更改为类似

    public interface Checker {
        void check() throws ValidationException;
    }
    
    public class YourClass {
       private List<Checker> checkers; // initialize through (dependency inhecjetd?) constructor parameter or by simply enumerating checker in the constructor; I personally prefer the first way
    
       public void yourMethod() {
         for(Checkech checker : checkers) {
            checker.check();
         }
       }
    }
    
    

    您显然可以在check 方法中添加参数,以便提供要验证的数据...

    更新

    如果您确实可以控制条件检查实现,则可以切换到类似的内容(请参阅@Alberto Venturini 的评论):

    public interface Checker {
        boolean check();
    
        String message();
    }
    
    public class YourClass {
       private List<Checker> checkers; // initialize through (dependency inhecjetd?) constructor parameter or by simply enumerating checker in the constructor; I personally prefer the first way
    
       public void yourMethod() {
         for(Checkech checker : checkers) {
            if(!checker.check()) {
                throw new ValidationException(checker.message());
            }        
         }
       }
    }
    

    您可以使用Map&lt;String, Checker&gt; 变量在第一个Checker 定义中实现类似的解决方案,该变量维护检查条件和相应错误消息之间的关联,但我绝对更喜欢@Alberto Venturini 提出的多态方法。

    我希望这种方法可以帮助您将代码移向更加开放封闭的解决方案!

    【讨论】:

    • 感谢您的建议。但是我的检查方法不会抛出任何异常,如果条件不满足它们就会抛出(条件返回 false)所以我有 3 种不同的检查方法和 3 种不同的错误消息
    • @dataProcs 您是否可以控制检查器代码 - 即,您可以更改 check 方法的签名以便它们抛出异常吗?如果这不可能,您可以使用错误消息扩展Checker 类的定义;然后,在您的方法中,使用if 块包装对checker.check() 的调用,例如:if (!checker.check()) { throw new ValidationException(checker.errorMsg); }
    • 我非常喜欢 Alberto Venturini 的建议:我更新我的回复以包含它!
    【解决方案2】:

    我看到您有 3 种不同的条件和 3 条不同的消息。 值得使用 Guava preconditions 之类的东西或自己编写。

    你的代码会喜欢

    checkState(check1stCondition(), message1);
    checkState(check2stCondition(), message2);
    

    你不会完全减少if's。但至少你增加了可读性。

    【讨论】:

      【解决方案3】:

      您可以尝试使用多态性来减少 if 语句并提高可维护性。

      只需使用这样的界面

      public interface Example {
      
      void check() throws ValidationException;
      }
      

      并实现不同的行为。

      【讨论】:

        【解决方案4】:

        有一种方法接近 OOP。注意:我不强求,只是展示一个替代方案。

        首先,您可以为每个条件创建一个新类。假设您对一些数据进行检查,它将如下所示:

        interface Condition {
            CustomData checkedData();
        }
        
        public class Condition1 implements Condition {
            private CustomData data;
        
            public Condition1(CustomData data) {
                this.data = data;
            }
        
            public Condition1(Condition condition) {
                this.data = condition.checkedData();
            }
        
            public CustomData checkedData() {
                // do condition checking here and return CustomData if it's ok
                // throw exception otherwise
            }
        }
        

        然后您可以将每个 Condition 包装在另一个中:

        CustomData data = new Condition1(
                              new Condition2(
                                  new Condition3(YOUR_DATA))).checkedData();
        

        您现在可以确定您的数据已经过检查并准备好进行进一步的工作。

        我相信它很容易维护。如果您需要一些新的检查,只需添加一些如上所述的小类并将您的数据包装在另一个 Condition 中。如果你想改变一些条件,你不必在通用代码中寻找它。你有单独的课程。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-25
          • 1970-01-01
          • 2020-10-13
          • 1970-01-01
          相关资源
          最近更新 更多