2

我有一个Service和一个Controller

服务中的每个方法都有其前提条件,例如:

  public void doSomething(Parameter para1 , Parameter para2 ...) {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    // continue do something 
  }

而在Controller层,有两种方法,一种是showForm()显示表单供用户输入;另一种是显示表单供用户输入。另一种是doApplyForm()接受形式并调用底层Service.doSomething()

以下是伪代码(我删除了一些BindingResultattr.addFlashAttribute代码):

  @Injected Service service;

  public String showForm() {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    return "showForm";
  }

  public String doApplyForm(@Validated Form form) {
    try {
      service.doSomething(para1 , para2 ...);
      return "redirect:/";
    } catch (Exception e) {
      // error handling 
      return "redirect:/error";
    }
  }

它运作良好,但我不满意。里面有难闻的气味

问题在于showForm(),它与 具有相同的先决条件Controller.doSomething()

如果Service.doSomething()以后再增加一个前置条件,就得Controller.showForm()做相应的修改。

我想知道是否有任何设计模式或框架来消除这种难闻的气味

Java8 的函数式解决方案是受欢迎的。

谢谢。

4

2 回答 2

1

您可以定义一个名为的 util 类Preconditions并将所有验证逻辑移到那里。这是一种常见的模式,并且有许多使用它的框架。例如,番石榴:前提条件文档

至少像这样,您if (condition) throw new exception将被封装并且更易于管理。

于 2015-11-11T12:22:55.687 回答
1

为服务请求引入一个参数对象,并将验证逻辑放入请求对象中。例如

public class DoSomethingRequest {

   private Parameter param1;
   private Parameter param2;


   public void validate(){
       if ( something wrong ) {
           throw new RuntimeException1();
       }
       if ( another thing wrong ) {
           throw new RuntimeException2();
       }
   }

}

您的服务会更轻松

public void doSomething(DoSomethingRequest request) {
    request.validate();
}

所以控制器

public String showForm() {
    DoSomethingRequest request = ... // obtained somehow
    request.validate();
    // ...
    return "showForm";
}

这将服务方法的先决条件封装在一个对象中。

于 2015-11-12T10:49:56.020 回答