Pregunta

Esta pregunta es una especie de continuación de mi anterior post: implementación de patrones visitante en java- ¿cómo es esta?

Me dieron un poco confundido mientras refactorización mi código. Estoy tratando de convertir mi patrón de visitante (explicado en el post anterior) en un patrón de estrategia compuesta. Estoy tratando de hacer algo como esto:

public interface Rule {
  public List<ValidatonError> check(Validatable validatable);
}

Ahora, me gustaría definir una regla como la siguiente:

public class ValidCountryRule  {
  public List<ValidationError> check(Validatable validatable) {
    // invokeDAO and do something, if violation met
    // add to a list of ValidationErrors.
    // return the list.
  }
}

Ahora, podría haber dos tipos diferentes objetos para ser validado. Estos dos podrían ser completamente diferentes: Decir que tengo una tienda que es Validatable, y luego un Schedule que es Validatable. Ahora, si me gustaría escribir un compuesto que se vería así:

class Validator implements Rule {
  private List<Rule> tests = new ArrayList<Rule>();

  public void addRule(Rule rule) {
    tests.add(rule);
  }

  public List<ValidationError> check(Visitable visitable) {
    List<ValidationError> list = new ArrayList<ValidationError>();
    for(Rule rule : tests) {
      list.addAll(rule.check(visitable);
    }
  }

  public Validator(ValidatorType type) {
    this.tests = type.getRules();
  }
}

Yo definiría un enum que define qué conjunto de controles de ir a donde ...

public Enum ValidatorType {
  public abstract List<Rule> getRules();
  STORE_VALIDATOR {
    public List<Rule> getRules() {
      List<Rule> rules = new ArrayList<Rule>();
      rules.add(new ValidCountryRule());
      rules.add(new ValidXYZRule());
    }

  // more validators
}

y, por último, me gustaría utilizar de esta manera:

Validator validator = new Validator(ValidatorType.STORE_VALIDATOR);
for (Store store : stores) {
  validator.check(store);
}

Tengo una sensación extraña que mi diseño es defectuoso. No me gustaba la idea de que mi interfaz Regla espera una Validatable. Podría sugerir cómo iba a mejorar esto?

Agradecemos su ayuda.

¿Fue útil?

Solución

Reemplazar validable por un parámetro de tipo genérico T para hacer el tipo de marco de validación segura.

public interface Rule<T> {
    public List<ValidationError> check(T value);
}

Vamos a extender nuestro marco con una interfaz de ValidationStrategy:

public interface ValidationStrategy<T> {
    public List<Rule<? super T>> getRules();
}

Se trata de reglas delimitadas por "? Super T", por lo que podemos añadir una regla de animal a un perro Validador (perro asumiendo extiende Animal). El Validador ahora se ve así:

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 void addRule(Rule<? super T> rule) {
        tests.add(rule);
    }

    public List<ValidationError> check(T value) {
        List<ValidationError> list = new ArrayList<ValidationError>();
        for (Rule<? super T> rule : tests) {
            list.addAll(rule.check(value));
        }
        return list;
    }
}

Ahora podemos implementar un DogValidationStrategy muestra de la siguiente manera:

public class DogValidationStrategy implements ValidationStrategy<Dog> {
    public List<Rule<? super Dog>> getRules() {
        List<Rule<? super Dog>> rules = new ArrayList<Rule<? super Dog>>();
        rules.add(new Rule<Dog>() {
            public List<ValidationError> check(Dog dog) {
                // dog check...
                return Collections.emptyList();
            }
        });
        rules.add(new Rule<Animal>() {
            public List<ValidationError> check(Animal animal) {
                // animal check...
                return Collections.emptyList();
            }
        });
        return rules;
    }
}

O, al igual que en la muestra, podemos tener una enumeración que proporciona varias estrategias de validación de perros:

public enum DogValidationType implements ValidationStrategy<Dog> {
    STRATEGY_1 {
        public List<Rule<? super Dog>> getRules() {
            // answer rules...
        }
    },
    // more dog validation strategies
}

Otros consejos

Cuando me enteré de patrones de diseño, que seguía tratando de encontrar lugares para utilizarlos. Desde entonces he aprendido que la prematura "patternization" es algo así como la optimización prematura. En primer lugar, tratar de hacerlo de una manera recta hacia adelante, y luego ver lo que le da problemas.

Trate de diseñar con interfaces mínimas y subclases. A continuación, aplicar cualquier patrón puede ser apropiado para las redundancias evidentes que encuentre. Me da la impresión de esta y la anterior entrada que puede ser sobre-arquitectura de su código.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top