私は私が作成した小さなクラスの検証クラスを用意していますが、ここでは優先順位付きルールを処理するように更新する必要があります。優先度の高いルールが満たされている場合は、ユーザーにメッセージ全体を追加するのではなく、ユーザーに単一のエラーメッセージを伝えるだけなので、それ以上の検証を実行する必要はありません。タイプセーフな優先順位付けされたルール
//Rule.java
public interface Rule<T> {
List<ErrorMessage> validate(T value);
}
//ValidationStrategy.java
public interface ValidationStrategy<T> {
public List<Rule<? super T>> getRules();
}
//Validator.java
public class Validator<T> implements Rule<T> {
private List<Rule<? super T>> tests = new ArrayList<Rule<? super T>>();
public Validator(ValidationStrategy<T> type) {
this.tests = type.getRules();
}
public List<ErrorMessage> validate(T value) {
List <ErrorMessage> errors = new ArrayList<ErrorMessage>();
for (Rule<? super T> rule : tests) {
errors.addAll(rule.check(value));
}
return errors;
}
}
私は優先順位のルールに対処するには、このコードを変更し、いくつかの問題を抱えています:ここで
は、私が持っているクラスのセットです。確かにルールエンジンを導入するのではなく、使用するように修正できるものがあります。
理想的には、私は、このようなルールを作成することができるだろう:更新されたクラスへ
private static final Rule<SomeClass> ensureAllFieldsNotBlank = new Rule<SomeClass>(RulePriority.HIGHEST) {
public List<ErrorMessage> check(SomeClass someClass) {
List<ErrorMessage> errors = new ArrayList<ErrorMessage>();
if (StringUtils.isBlank(someClass.getValue1())
&& StringUtils.isBlank(someClass.getValue2())
&& StringUtils.isBlank(someClass.getValue3())) {
errors.add("Provide a response for \"" + someClass.getName() + "\"");
}
return errors;
}
};
編集:ルールの比較を処理するための抽象基本クラスを作成する方法についてどのように
//ValidationStrategy.java
public interface ValidationStrategy<T> {
public List<Rule<? super T>> getRules(RulePriority rulePriority);
}
//RulePriority.java
public enum RulePriority { HIGHEST, DEFAULT, LOWEST; }
//Validator.java
public class Validator<T> implements Rule<T> {
private List<Rule<? super T>> tests = new ArrayList<Rule<? super T>>();
private ValidationStrategy<T> validationStrategy;
public Validator(ValidationStrategy<T> validationStrategy) {
this.validationStrategy = validationStrategy;
for (RulePriority rp : RulePriority.values()) {
this.tests.addAll(validationStrategy.getRules(rulePriority));
}
}
public List<ErrorMessage> validate(T value) {
List<ErrorMessage> errors = new ArrayList<String>();
for (RulePriority rp : RulePriority.values()) {
for (Rule<? super T> rule : validationStrategy.getRules(rp)) {
errors.addAll(rule.validate(value));
}
if (errors.size() > 0) {
break;
}
}
return errors;
}
私はこのアプローチが気に入っていますが、 'compareTo()'を 'equals()'と一貫性を持たせるのは簡単だと指摘したいだけです。等しい場合は0を返し、そうでなければ何も返しません。 – CurtainDog
これは、すべてのPrioritizedRuleオブジェクトがクリアで定義された合計順序を有することを要する。つまり、非常に異なるデータであり、非常に異なるデータであるルールに対しては、PrioritizedRule自体が「タイブレイカー」でなければならない。これは一般的に保証することが不可能に近いです。ハッシュコード(hashCode()!がすべてhashCode()!をオーバーライドした場合)をタイブレイカーとして使用しても、必ずしも安全であるとは限りません。つまり、重要なトータルオーダーがない限り、常に衝突する可能性があります。安全に行うための情報。すべてのルールオブジェクトにtiebreakersとしてのGUIDを強制しますか? –
私は同様のアプローチを考えていましたが、エラーリストを返す前にすべてのルールを優先して実行する必要があります。したがって、2つのルールが最高の優先度を持ち、4がデフォルトの優先度を持ち、2つの最高レベルのルールが合格した場合、4つのルールすべてをデフォルトの優先度で検証する必要があります。 – Scott