Java 类型安全优先规则

Java 类型安全优先规则,java,validation,generics,Java,Validation,Generics,我创建了一小组验证类,这些类对我很有用,但是现在我需要更新它们来处理优先级规则。如果满足高优先级规则,那么我不需要运行任何进一步的验证,因为我们将只告诉用户一条错误消息,而不是向用户添加整个消息集 以下是我的一组课程: //Rule.java public interface Rule<T> { List<ErrorMessage> validate(T value); } //ValidationStrategy.java public interface V

我创建了一小组验证类,这些类对我很有用,但是现在我需要更新它们来处理优先级规则。如果满足高优先级规则,那么我不需要运行任何进一步的验证,因为我们将只告诉用户一条错误消息,而不是向用户添加整个消息集

以下是我的一组课程:

//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;
    }
}
//Rule.java
公共接口规则{
列表验证(T值);
}
//ValidationStrategy.java
公共接口验证策略{

public List创建一个抽象基类来处理规则比较怎么样:

abstract class PrioritizedRule<T> implements Rule<T>, Comparable<PrioritizedRule<T>>{
    public int compareTo(PrioritizedRule<T> other){
        //Implement something that compares rule priorities here.
        //This will probably require support from the constructor, which-
        //since this is abstract- must be Protected.
抽象类实现规则,可比较{
公共int比较(其他){
//在这里实现一些比较规则优先级的东西。
//这可能需要构造器的支持,构造器-
//因为这是抽象的,所以必须加以保护。
从那里,您的PrioritizedValidator(需要PrioritizedRule)将在Validate开始时对其集合进行排序()(如果自上次验证以来其规则集合已被修改;这是对集合进行排序的正确时间,因为如果存在连续修改,我们不希望在每次修改时重复排序,或者如果不需要,则执行排序),并且如果其错误消息列表在规则优先级之间的转换期间不为空,则验证循环应提前退出:

public List<ErrorMessage> validate(T value) {
    if(ruleSetModified){
        //be careful: validate becomes unsafe for multithreading here, even if you
        //aren't modifying the ruleset; if this is a problem, implement locking
        //inside here. Multiple threads may try to sort the collection, but not
        //simultaneously. Usually, the set won't be modified, so locking before
        //the test is much, much slower. Synchronizing the method is safest,
        //but carries a tremendous performance penalty
        Collections.sort(rule);
        ruleSetModified = false;
    }
    List <ErrorMessage> errors = new ArrayList<String>();
        PrioritizedRule prev = null;
        for (PrioritizedRule<? super T> rule : tests) {
            if(prev != null && prev.compareTo(rule) != 0 && !errors.isEmpty()){
                return errors;
            }
            errors.addAll(rule.check(value));
            prev = rule;
        }
        return errors;
}
公共列表验证(T值){
如果(规则集修改){
//注意:这里的验证对于多线程来说是不安全的,即使您
//不修改规则集;如果这是一个问题,请实现锁定
//多个线程可能会尝试对集合进行排序,但不会
//同时。通常,集合不会被修改,所以在
//测试要慢得多同步方法是最安全的,
//但是会带来巨大的性能损失
集合。排序(规则);
ruleSetModified=false;
}
列表错误=新建ArrayList();
优先级为prev=null;

例如,我喜欢这种方法,但我只想指出,很容易使
compareTo()
equals()保持一致
-只需调用它!如果它们相等,则返回0,否则返回除此之外的任何值。这要求所有PrioritizedRule对象都有一个明确定义的总顺序-简而言之,PrioritizedRule本身必须有一个“tiebreaker”对于类型非常不同、数据非常不同的规则。这通常几乎不可能保证。即使使用哈希代码(如果所有内容都覆盖hashCode()!)作为一个tiebreaker并不一定是安全的-除非你有一个有意义的总顺序,否则总是有发生冲突的机会,并且作为一个抽象基类,你没有真正的信息来安全地这样做。强制所有规则对象都有guid作为tiebreaker?我正在考虑类似的方法,但我需要处理我运行的情况在返回错误列表之前,所有规则都具有一个优先级。因此,如果我有两个具有最高优先级的规则和4个具有默认优先级的规则,并且两个最高级别的规则都通过了,那么我需要验证具有默认优先级的所有4个规则。在这种情况下,这稍微有些尴尬,但并不可怕。您需要做的就是跟踪p上一个规则,并且仅在优先级更改时评估错误列表是否为空。正在修改的代码段可能会在您阅读本文时被修改。您是正确的,我最终修改了验证器。幸运的是,我的规则在编译时设置完成,它们实际上只会根据输入进行更改;但是我无法更改这些规则在运行时根据我正在处理的项的类型应用。
abstract class PrioritizedRule<T> implements Rule<T>, Comparable<PrioritizedRule<T>>{
    public int compareTo(PrioritizedRule<T> other){
        //Implement something that compares rule priorities here.
        //This will probably require support from the constructor, which-
        //since this is abstract- must be Protected.
public List<ErrorMessage> validate(T value) {
    if(ruleSetModified){
        //be careful: validate becomes unsafe for multithreading here, even if you
        //aren't modifying the ruleset; if this is a problem, implement locking
        //inside here. Multiple threads may try to sort the collection, but not
        //simultaneously. Usually, the set won't be modified, so locking before
        //the test is much, much slower. Synchronizing the method is safest,
        //but carries a tremendous performance penalty
        Collections.sort(rule);
        ruleSetModified = false;
    }
    List <ErrorMessage> errors = new ArrayList<String>();
        PrioritizedRule prev = null;
        for (PrioritizedRule<? super T> rule : tests) {
            if(prev != null && prev.compareTo(rule) != 0 && !errors.isEmpty()){
                return errors;
            }
            errors.addAll(rule.check(value));
            prev = rule;
        }
        return errors;
}