Java 面向对象的用户输入验证设计
目前,我试图在设计一些东西时考虑OO原则。比如说,在处理用户输入之前,我需要验证它。根据OO,单独的验证器类将是正确的方法。这将如下所示:Java 面向对象的用户输入验证设计,java,oop,coding-style,Java,Oop,Coding Style,目前,我试图在设计一些东西时考虑OO原则。比如说,在处理用户输入之前,我需要验证它。根据OO,单独的验证器类将是正确的方法。这将如下所示: public class Validator{ public void validate(String input) throws ValidationException{ if (input.equals("")) throw new ValidationException("Input was empty");
public class Validator{
public void validate(String input) throws ValidationException{
if (input.equals("")) throw new ValidationException("Input was empty");
}
}
然后,我的处理类(之前通过依赖项注入获得了validator对象)将调用validator.validate(input)
这种设计的一个优点是
static
。我也读过很多次(静态)Util类是糟糕的OO设计。那么,在保留我提到的两个优点的同时,如何使用更多的OO来实现这一点呢
PS:也许,OO只是解决这类问题的一个糟糕的方法。但是,我希望看到OO解决方案的样子,并形成我自己的观点。您示例中的验证程序没有状态(也不需要任何状态),但另一个验证程序可能需要状态(比如使用格式): 例如:
public class RegExValidator {
private Pattern pattern;
public RegExValidator(String re) {
pattern = Pattern.compile(re);
}
public void validate(String input) throws ValidationException {
if (!pattern.matcher(input).matches()) {
throw new ValidationException("Invalid syntax [" + input + "]");
}
}
}
关注问题的OOP方面(而不是异常是否是处理验证的正确方法): 为什么只有一个验证器
interface Validator<T> {
void validate(T toValidate) throws ValidationException;
}
你可以很容易地测试它。
事实上,如果您使用Java 8,这将是一个功能接口,因此单个实用程序类可以承载多个验证器:
class ValidationUtil {
public static void emptyString(String val) // same code as above
}
而ValidationUtil::emptyString
将实现Validator
。
您可以将多个验证器与一个复合模式相结合
如果你需要的话,你也可以有一个带有状态的验证器
class ListIsSortedValidator implements Validator<Integer> {
private int lastInt = Integer.MIN_VALUE;
public void validate(Integer val) throw ValidationException {
if (val < lastInt) throw new ValidationException("not sorted");
lastInt = val;
}
}
类ListIsSortedValidator实现验证器{
private int lastInt=Integer.MIN_值;
公共void validate(整数val)抛出ValidationException{
如果(val
例如,您可以使用它来验证列表:
List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);
List List=createList();
Validator Validator=新的ListIsSortedValidator();
list.forEach(validator::validate);
当然这取决于具体情况,但我认为你的直觉是正确的。这种设计可以更加面向对象
不仅仅是验证器
没有状态,这是一个纯粹的机械指标,表明它可能不是一个正确的抽象,而且名称本身告诉我们一些事情。通常,Validator
(甚至EmptyStringValidator
)不是问题域的一部分。当你必须创造一些纯技术性的东西时,这总是一个坏兆头(尽管有时这是两害相权取其轻)
我假设您不是在编写web框架,而是在尝试编写具有某个域的应用程序。例如,它有用户注册。然后,RegistrationForm
是问题域的一部分。用户知道“登记表”,你可以谈论它,他们会知道你的意思
在这种情况下,面向对象的验证解决方案是,该对象负责在自身“提交”期间对自身进行验证
public final class注册表单扩展表单{
...
@凌驾
公开作废提交(){
//在这里进行验证
//如果出现问题,请将输入字段设置为错误
//如果一切都好,就做逻辑
}
}
我知道这不是web框架通常看到或支持的解决方案。但这就是面向对象解决方案的样子
要始终牢记的两个要点是:
验证器
(如果这不是应用程序的域)我认为最好将所有验证错误写入集合并返回。然后,您可以根据需要处理错误(异常、正确的html页面、json响应等)。假设用户必须用10个字段填写某个表单-您的设计将在第一个字段上引发异常,而不会告诉其他9个字段。所以您的验证器只用于检查数据并返回结果,其他类将编写响应。您是对的,我以前没有考虑过这一点。
List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);