我有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()
。
以下是伪代码(我删除了一些BindingResult
,attr.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的功能解决方案。
感谢。
答案 0 :(得分:1)
您可以定义名为Preconditions
的util类,并将所有验证逻辑移到那里。它是一种常见模式,有许多框架可以利用它。例如,Guava:Preconditions docs。
至少这样,if (condition) throw new exception
将被封装并更易于管理。
答案 1 :(得分:1)
Introduce a parameter object for the service request and put the validation logic into the request object. E.g.
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();
}
}
}
Your service will be more easy
public void doSomething(DoSomethingRequest request) {
request.validate();
}
so the controller
public String showForm() {
DoSomethingRequest request = ... // obtained somehow
request.validate();
// ...
return "showForm";
}
This encapsulates the service method's preconditions in an object.