我试图重构此代码
private void validate(Customer customer) {
List<String> errors = new ArrayList<>();
if (customer == null) {
errors.add("Customer must not be null");
}
if (customer != null && customer.getName() == null) {
errors.add("Name must not be null");
}
if (customer != null && customer.getName().isEmpty()) {
errors.add("Name must not be empty");
}
if (customer != null) {
Customer customerFromDb = customerRepository.findByName(customer.getName());
if (customerFromDb != null) {
errors.add("Customer already present on db");
}
}
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
}
我读过这篇文章Business logic validation patterns & advices
我想为我的实体和实体字段构建一个通用验证器,我写了这个
private void validate(Customer customer) {
List<ValidationRule> validationRules = new ArrayList<>();
validationRules.add(new NotNullValidationRule(customer));
validationRules.add(new NotNullValidationRule(customer, Customer::getName));
validationRules.add(new NotEmptyValidationRule(customer, Customer::getName));
validationRules.add(new NotExistValidationRule(customer -> customerRepository.findByName(customer.getName())));
Validator.validate(validationRules);
}
和Validator类
public class Validator {
public static void validate(List<ValidationRule> validationRules) {
final List<String> errors = new ArrayList<>();
for (final ValidationRule rule : validationRules) {
final Optional<String> error = rule.validate();
if (error.isPresent()) {
errors.add(error.get());
}
}
if (!errors.isEmpty()) {
throw new ValidationException(errors);
}
}
}
但我不知道如何实现接口ValidationRule和其他类(NotNullValidationRule,NotEmptyValidationRule,NotExistValidationRule)
答案 0 :(得分:0)
我会写一些类似的东西:
CommonValidations.notNull(errors, customer);
if (customer != null) {
CommonValidations.notEmpty(errors, customer.getName());
}
customerCustomeBeanValidations.validName(errors, customer.getName());
customerCustomeBeanValidations.notExist(errors, customer.getName());
答案 1 :(得分:0)
在您引用的链接中,使用Strategy设计模式建议接受的答案,然后举例说明接口和实现。在您的情况下,您将创建一个新的接口ValidationRule,至少有一个方法validate(),然后您将创建每个实现该接口的具体类(NotNullValidationRule,NotEmptyValidationRule,AlreadyExistValidationRule)。
答案 2 :(得分:0)
我找到了这个解决方案:
我创建一个接口ValidationRule
import java.util.Optional;
public interface ValidationRule {
Optional<ValidationError> validate();
}
以及一些实现行为的类
public class NotNullValidationRule implements ValidationRule {
private Object object;
private String field;
public NotNullValidationRule(Object object, String field) {
this.object = object;
if (field == null || field.isEmpty()) {
throw new IllegalArgumentException("field must not be null or emtpy");
}
this.field = field;
}
@Override public Optional<ValidationError> validate() {
if (object == null) {
return Optional.empty();
}
try {
Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
if (value == null) {
ValidationError validationError = new ValidationError();
validationError.setName(object.getClass().getSimpleName() + "." + field);
validationError.setError("Field " + field + " is null");
return Optional.of(validationError);
}
}
catch (Exception e) {
throw new IllegalStateException("error during retrieve of field value");
}
return Optional.empty();
}
}
另一个我传递方法调用的地方:
package it.winetsolutions.winactitime.core.service.validation;
import java.beans.PropertyDescriptor;
import java.util.Optional;
import java.util.function.Function;
public class NotExistValidationRule implements ValidationRule {
Object object;
String field;
Function<? super String, ? super Object> function;
public NotExistValidationRule(Object object, String field, Function<? super String, ? super Object> function) {
this.object = object;
if (field == null || field.isEmpty() || function == null) {
throw new IllegalArgumentException("field and function must not be null or emtpy");
}
this.field = field;
this.function = function;
}
@Override public Optional<ValidationError> validate() {
if (object == null) {
return Optional.empty();
}
try {
Object value = new PropertyDescriptor(field, object.getClass()).getReadMethod().invoke(object);
Long id = (Long) new PropertyDescriptor("id", object.getClass()).getReadMethod().invoke(object);
Object result = function.apply(value == null ? (String) value : ((String) value).trim());
if (result != null &&
!id.equals((Long) new PropertyDescriptor("id", result.getClass()).getReadMethod().invoke(result))) {
ValidationError validationError = new ValidationError();
validationError.setName(object.getClass().getSimpleName() + "." + field);
validationError.setError("Element with " + field +": " + value + " already exists");
return Optional.of(validationError);
}
}
catch (Exception e) {
throw new IllegalStateException("error during retrieve of field value");
}
return Optional.empty();
}
}