Я потерял счетчик количества раз, которое я видел код, который быстро и без ошибок проверяет состояние чего-либо, используя такой подход:
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 . |