在提出我的解决方案之前有几点:
异常应该用于或多或少的异常情况。根据您的说法,用户提交错误数据的情况并不少见。
当您的Person
班级增长时,您将添加越来越多必须满足的条件才能使其有效。
除了例外情况,您一次只能显示一个错误,如果提交的数据有多个错误怎么办?
将验证方法放入您的Person
班级似乎不正确。例如,如果您想在应用程序的不同位置使用不同的验证策略怎么办?
所以,我会让你的 Person 类没有验证逻辑:
class Person {
final String name;
final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
然后实现一些需要一个人并对其进行验证的类。这个想法是有不同的验证器,每个验证器都有自己的验证规则和自己的验证消息。enum
很高兴实现这一目标:
enum Validator {
NOT_NULL_NAME("Name must not be null") {
@Override
public boolean validate(Person person) {
return person.name != null;
}
},
AGE_GREATER_THAN_ZERO("Age must be greater than zero") {
@Override
public boolean validate(Person person) {
return person.age > 0;
}
};
final String errorMessage;
private Validator(String errorMessage) {
this.errorMessage = errorMessage;
}
public abstract boolean validate(Person person);
}
看看用不同的消息添加一些新条件有多容易?只是另一个枚举实例。
现在创建一个用于验证人员的类。它只是遍历所有验证器并收集错误消息。
class PersonValidator {
private final List<String> errors = new ArrayList<String>();
public PersonValidator(Person person) {
for (Validator validator : Validator.values()) {
if (!validator.validate(person)) {
errors.add(validator.errorMessage);
}
}
}
public boolean isValid() {
return errors.isEmpty();
}
public Collection<String> getErrors() {
return errors;
}
}
如何使用它的示例:
public static void main(String... args) {
Person[] people = { new Person(null, 0),
new Person(null, 42),
new Person("Joe", 0),
new Person("Joe", 42) };
for (int i = 0; i < people.length; i++) {
PersonValidator validator = new PersonValidator(people[i]);
System.out.println(String.format("Person no %s is %s valid. %s",
i,
validator.isValid() ? "" : "not",
Joiner.on(", ").join(validator.getErrors())));
}
}
以上打印:
Person no 0 is not valid. Name must not be null, Age must be greater than zero
Person no 1 is not valid. Name must not be null
Person no 2 is not valid. Age must be greater than zero
Person no 3 is valid.
很整洁吧?