可以通过组合来委派任何逻辑如果逻辑要在程序执行期间动态变化,则可以。像您解释的那样,复杂的验证与通过组合委派给另一个类的验证一样,都是很好的候选人。
请记住,尽管验证可以在不同的时刻进行。
像您的示例中那样实例化一个具体的验证器是一个坏主意,因为它将Event类耦合到该特定的验证器。
假设您没有使用任何DI框架。
您可以将验证器添加到构造函数中,或使用setter方法将其注入。我建议工厂中的创建者方法将Event和Validator实例化,然后将其传递给事件构造器或setValidator方法。
显然,应该编写Validator接口和/或抽象类,以便您的类依赖于它,而不依赖于任何具体的验证器。
在构造函数中执行validate方法可能会出现问题,因为您要验证的所有状态可能尚未就绪。
我建议您创建一个Validable接口并让您的类实现它,该接口可以具有validate()方法。
这样,您的应用程序的上层组件便会随意调用validate方法(然后将其委托给Validator成员)。
==> IValidable.java <==
import java.util.List;
public interface IValidable {
public void setValidator(IValidator<Event> validator_);
public void validate() throws ValidationException;
public List<String> getMessages();
}
==> IValidator.java <==
import java.util.List;
public interface IValidator<T> {
public boolean validate(T e);
public List<String> getValidationMessages();
}
==> Event.java <==
import java.util.List;
public class Event implements IValidable {
private IValidator<Event> validator;
@Override
public void setValidator(IValidator<Event> validator_) {
this.validator = validator_;
}
@Override
public void validate() throws ValidationException {
if (!this.validator.validate(this)){
throw new ValidationException("WTF!");
}
}
@Override
public List<String> getMessages() {
return this.validator.getValidationMessages();
}
}
==> SimpleEventValidator.java <==
import java.util.ArrayList;
import java.util.List;
public class SimpleEventValidator implements IValidator<Event> {
private List<String> messages = new ArrayList<String>();
@Override
public boolean validate(Event e) {
// do validations here, by accessing the public getters of e
// propulate list of messages is necessary
// this example always returns false
return false;
}
@Override
public List<String> getValidationMessages() {
return this.messages;
}
}
==> ValidationException.java <==
public class ValidationException extends Exception {
public ValidationException(String message) {
super(message);
}
private static final long serialVersionUID = 1L;
}
==> Test.java <==
public class Test {
public static void main (String args[]){
Event e = new Event();
IValidator<Event> v = new SimpleEventValidator();
e.setValidator(v);
// set other thins to e like
// e.setPlayers(player1,player2,player3)
// e.setNumberOfMatches(3);
// etc
try {
e.validate();
} catch (ValidationException e1) {
System.out.println("Your event doesn't comply with the federation regulations for the following reasons: ");
for (String s: e.getMessages()){
System.out.println(s);
}
}
}
}