ロジックがプログラムの実行中に動的に変化する場合、合成によってロジックを委任しても構いません。あなたが説明するような複雑な検証は、合成を介して別のクラスに委任されるものと同じくらい良い候補です。
ただし、検証は異なる瞬間に発生する可能性があることを忘れないでください。
あなたの例のように具体的なバリデータをインスタンス化することは、Eventクラスをその特定のバリデータに結合するため、悪いアイデアです。
DIフレームワークを使用していないと仮定しましょう。
コンストラクターにバリデーターを追加するか、setterメソッドを使用して注入できます。ファクトリー内のクリエーターメソッドは、イベントとバリデーターの両方をインスタンス化し、イベントコンストラクターまたはsetValidatorメソッドで渡すことをお勧めします。
明らかに、Validatorインターフェースまたは抽象クラスは、具体的なバリデーターではなく、クラスに依存するように作成する必要があります。
コンストラクターでvalidateメソッドを実行すると、検証するすべての状態がまだ整っていない可能性があるため、問題が発生する可能性があります。
Validableインターフェースを作成し、クラスに実装させることをお勧めします。そのインターフェースにはvalidate()メソッドを含めることができます。
そのようにして、アプリケーションの上位コンポーネントは、自由にvalidateメソッドを呼び出します(このメソッドは、バリデータメンバーに委任されます)。
==> 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);
}
}
}
}