Я потерял счетчик количества раз, которое я видел код, который быстро и без ошибок проверяет состояние чего-либо, используя такой подход:
|
01
02
03
04
05
06
07
08
09
10
|
public class PersonValidator { public boolean validate(Person person) { boolean valid = person != null; if (valid) valid = person.givenName != null; if (valid) valid = person.familyName != null; if (valid) valid = person.age != null; if (valid) valid = person.gender != null; // ...and many more }} |
Это работает, но это подход грубой силы, который заполнен повторением из-за действительной проверки. Если ваш стиль кода применяет скобки для операторов if (+1 для этого), ваш метод также в три раза длиннее и увеличивается каждый раз, когда в валидатор добавляется новая проверка.
Используя новый потоковый API в Java 8, мы можем улучшить это, взяв защитное условие if (valid) и сделав общий валидатор, который обрабатывает сантехнику для вас.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import java.util.LinkedList;import java.util.List;import java.util.function.Function; public class GenericValidator implements Function { private final List> validators = new LinkedList<>(); public GenericValidator(List> validators) { this.validators.addAll(validators); } @Override public Boolean apply(final T toValidate) { // a final array allows us to change the boolean value within a lambda final boolean[] guard = {true}; return validators.stream() // only send the validator downstream if // previous validations were successful .filter(validator -> guard[0]) .map(validator -> validator.apply(toValidate)) // update the guard condition .map(result -> { guard[0] = result; return result; }) // Logically AND the results of the applied validators .reduce(guard[0], (b1, b2) -> b1 && b2); }} |
Используя это, мы можем переписать Person validator, чтобы он стал спецификацией необходимых проверок.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
public class PersonValidator extends GenericValidator { private static final List> VALIDATORS = new LinkedList<>(); static { VALIDATORS.add(person -> person.givenName != null); VALIDATORS.add(person -> person.familyName != null); VALIDATORS.add(person -> person.age != null); VALIDATORS.add(person -> person.gender != null); // ...and many more } public PersonValidator() { super(VALIDATORS); }} |
PersonValidator и все другие ваши валидаторы теперь могут полностью сосредоточиться на валидации. Поведение не изменилось — проверка по-прежнему быстро проходит. Там нет котельной плиты, что хорошо.
Этот идет в наборе инструментов.
| Ссылка: | Безотказные проверки с использованием потоков Java 8 от нашего партнера JCG Стива Чалонера в блоге Objectify . |