我对“组合器”模式得到的结果有点问题。
public interface CustomerRegistrationValidator
extends Function<Customer, ValidationResult> {
static CustomerRegistrationValidator isEmailValid() {
return customer -> customer.getEmail().contains("@") ?
ValidationResult.SUCCESS : ValidationResult.EMAIL_NOT_VALID;
}
static CustomerRegistrationValidator isPhoneNumberValid() {
return customer -> customer.getPhoneNumber().startsWith("+0") ?
ValidationResult.SUCCESS : ValidationResult.PHONE_NUMBER_NOT_VALID;
}
static CustomerRegistrationValidator isAnAdult() {
return customer -> Period.between(customer.getDob(), LocalDate.now()).getYears() > 16 ?
ValidationResult.SUCCESS : ValidationResult.IS_NOT_AN_ADULT;
}
default CustomerRegistrationValidator and (CustomerRegistrationValidator other) {
return customer -> {
ValidationResult result = this.apply(customer);
return result.equals(ValidationResult.SUCCESS) ? other.apply(customer) : result;
};
}
enum ValidationResult {
SUCCESS,
PHONE_NUMBER_NOT_VALID,
EMAIL_NOT_VALID,
IS_NOT_AN_ADULT
}
}
public class Main {
public static void main(String[] args) {
Customer customer = new Customer(
"Alice",
"alicegmail.com",
"089877878",
LocalDate.of(2000, 1, 1)
);
ValidationResult result = CustomerRegistrationValidator.isEmailValid()
.and(CustomerRegistrationValidator.isPhoneNumberValid())
.and(CustomerRegistrationValidator.isAnAdult())
.apply(customer);
System.out.println(result);
if (result != ValidationResult.SUCCESS) {
throw new IllegalStateException(result.name());
}
}
}
假设这些方法(isAnAdult,isEmailValid)是否有两个错误。为什么它只从枚举类型中打印一个,在我的例子中是“EMAIL_NOT_VALID”而不是两个,而第二个我的意思是“IS_NOT_AN_ADULT”?
如果您希望验证器能够返回多个 distinct 结果代码(枚举),则需要将返回类型更改为
Set<ValidationResult>
,或者更具体地说是 EnumSet
。
例如像这样:
interface CustomerRegistrationValidator
extends Function<Customer, EnumSet<ValidationResult>> {
static final EnumSet<ValidationResult> SUCCESS_ONLY = EnumSet.of(ValidationResult.SUCCESS);
static CustomerRegistrationValidator isEmailValid() {
return customer -> customer.getEmail().contains("@") ?
SUCCESS_ONLY : EnumSet.of(ValidationResult.EMAIL_NOT_VALID);
}
static CustomerRegistrationValidator isPhoneNumberValid() {
return customer -> customer.getPhoneNumber().startsWith("+0") ?
SUCCESS_ONLY : EnumSet.of(ValidationResult.PHONE_NUMBER_NOT_VALID);
}
static CustomerRegistrationValidator isAnAdult() {
return customer -> Period.between(customer.getDob(), LocalDate.now()).getYears() > 16 ?
SUCCESS_ONLY : EnumSet.of(ValidationResult.IS_NOT_AN_ADULT);
}
default CustomerRegistrationValidator and(CustomerRegistrationValidator other) {
return customer -> {
EnumSet<ValidationResult> thisResult = this.apply(customer);
EnumSet<ValidationResult> otherResult = other.apply(customer);
if (thisResult.equals(SUCCESS_ONLY))
return otherResult;
if (otherResult.equals(SUCCESS_ONLY))
return thisResult;
EnumSet<ValidationResult> combinedResult = EnumSet.copyOf(thisResult);
combinedResult.addAll(otherResult);
return combinedResult;
};
}
}
In this modified code, the CustomerRegistrationValidator interface now returns a List<CustomerRegistrationValidator.ValidationResult> instead of a single ValidationResult. Each validator method creates an empty list of errors and adds the relevant error to the list if the validation fails.
The and method has been updated to accumulate errors from both the current validator and the other validator. It creates a new list of errors, applies the current validator (this), and adds any errors to the list. Then it applies the other validator and adds any errors from that validator as well.
Now, when you apply the validators to a customer, you will get a list of errors instead of a single error. You can then handle the errors accordingly, such as printing them or performing any other necessary actions.
import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
public interface CustomerRegistrationValidator extends Function<Customer, List<CustomerRegistrationValidator.ValidationResult>> {
static CustomerRegistrationValidator isEmailValid() {
return customer -> {
List<CustomerRegistrationValidator.ValidationResult> errors = new ArrayList<>();
if (!customer.getEmail().contains("@")) {
errors.add(CustomerRegistrationValidator.ValidationResult.EMAIL_NOT_VALID);
}
return errors;
};
}
static CustomerRegistrationValidator isPhoneNumberValid() {
return customer -> {
List<CustomerRegistrationValidator.ValidationResult> errors = new ArrayList<>();
if (!customer.getPhoneNumber().startsWith("+0")) {
errors.add(CustomerRegistrationValidator.ValidationResult.PHONE_NUMBER_NOT_VALID);
}
return errors;
};
}
static CustomerRegistrationValidator isAnAdult() {
return customer -> {
List<CustomerRegistrationValidator.ValidationResult> errors = new ArrayList<>();
if (Period.between(customer.getDob(), LocalDate.now()).getYears() <= 16) {
errors.add(CustomerRegistrationValidator.ValidationResult.IS_NOT_AN_ADULT);
}
return errors;
};
}
default CustomerRegistrationValidator and(CustomerRegistrationValidator other) {
return customer -> {
List<CustomerRegistrationValidator.ValidationResult> errors = new ArrayList<>();
errors.addAll(this.apply(customer));
errors.addAll(other.apply(customer));
return errors;
};
}
enum ValidationResult {
SUCCESS,
PHONE_NUMBER_NOT_VALID,
EMAIL_NOT_VALID,
IS_NOT_AN_ADULT
}
}
Customer customer = new Customer("Alice", "alicegmail.com", "089877878", LocalDate.of(2000, 1, 1));
List<CustomerRegistrationValidator.ValidationResult> errors = CustomerRegistrationValidator.isEmailValid()
.and(CustomerRegistrationValidator.isPhoneNumberValid())
.and(CustomerRegistrationValidator.isAnAdult())
.apply(customer);
if (!errors.isEmpty()) {
for (CustomerRegistrationValidator.ValidationResult error : errors) {
System.out.println(error);
}
// Handle the errors accordingly
} else {
// Registration is successful
}