У меня есть следующий сценарий: два помощника проверки
StringValidationHelper ...
public class StringValidationHelper {
public static Validation<String> notNull =
SimpleValidation.from(s -> s != null, "must not be null.");
public static Validation<String> moreThan(int size) {
return SimpleValidation.from(
s -> s.length() >= size,
String.format ("must have more than %s chars.", size));
}
... // More methods (lessThan, etc)}
... и NumberValidationHelper.
public class NumberValidationHelper {
public static Validation<Number> notNull =
SimpleValidation.from(n -> n != null, "must not be null");
public static <N extends Number & Comparable<N>> Validation<N> lowerThan(N max){
return SimpleValidation.from(
n -> n.compareTo(max) == -1,
String.format("must be lower than %s.", max));
}
... // More methods like (greaterThan, etc)}
Метод из - это статический фабричный метод, который получает предикат и сообщение о возможной проверке завершается неудачей.
public class SimpleValidation<K> implements Validation<K>{
private Predicate<K> predicate;
private String onErrorMessage;
private SimpleValidation(Predicate<K> predicate, String onErrorMessage) {
this.predicate = predicate;
this.onErrorMessage = onErrorMessage;
}
public static <K> SimpleValidation<K> from(Predicate<K> predicate, String onErrorMessage){
return new SimpleValidation<>(predicate, onErrorMessage);
}
... // Omitted for simplicity
}
Благодаря интерфейсу проверки вы можете наслаждаться удивительно плавным интерфейсом
@FunctionalInterface
public interface Validation<K> {
... // Omitted for simplicity
default Validation<K> and(Validation<K> other) {
return param -> {
ValidationResult firstResult = this.test (param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
... // Omitted for simplicity
}
Таким образом, я могу начать, например, проверку с использованием замыкания notNull.
Пример: с NumberValidationHelper
public class MyValidate {
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
}
Эта структура проверки, которую я разработал на основе этой статьи.
Ну, notNull анклавирует поведение, не зависящее от типа, поэтому я хотел бы удалить дублирование этих двух помощников.
Я не нахожу очевидную форму, не теряя интерфейс жидкости.
Поскольку переменная является статической, вы не можете, например, использовать обобщенные значения и расширять поведение.
public abstract class GenericHelper<K> {
public static Validation<K> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
Также меня не беспокоит ввод Validation с Object, как показано ниже:
public abstract class GenericHelper {
public static Validation<Object> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
... потому что в цепочке вызовов это даст ошибку компиляции, так как результатом notNull будет Validation , и он будет ожидать Validation
notNull.and(lowerThan(100)).test(toValidate).isValid(); //Does not compile
Есть ли способ использовать функции функций Java 8, которые поддерживают общий интерфейс этого интерфейса, избегая решений, которые я пробовал выше?
благодарный