OOP-用于验证用户输入的设计

时间:2018-01-09 11:48:59

标签: java oop coding-style

目前,我尝试用OO原则设计一些东西。所以,让我们说,在处理用户输入之前,我需要对其进行验证。根据OO,单独的Validator类将是正确的方法。这看起来如下:

    public class Validator{
      public void validate(String input) throws ValidationException{
        if (input.equals("")) throw new ValidationException("Input was empty");
      }
    }

然后,我的处理类在通过依赖注入之前得到验证器对象将调用validator.validate(input)

关于这种设计的一个好处是,

  1. 我的处理类可以通过DI获得验证器的模拟,这使得测试更容易
  2. Validator类可以独立测试
  3. 然而,我的疑问是在Validator的设计中。根据OO,它错过了某种状态。使用此设计,它是util类,验证方法可以是static。我读了很多次(静态)Util类是糟糕的OO设计。那么,如何在保持我提到的两个优势的同时用更多的OO来完成这项工作呢?

    PS:也许,OO对于这类问题来说只是一个糟糕的解决方案。但是,我想看看OO解决方案的外观如何并形成我自己的观点。

3 个答案:

答案 0 :(得分:1)

示例中的验证器没有状态(并且不需要任何状态),但是另一个验证器可能需要一个(比如格式化):

示例:

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 + "]");
        }
    }
}

答案 1 :(得分:1)

专注于问题的OOP方面(而不是问题,如果异常是处理验证的正确方法):

为什么要有一个验证器?

interface Validator<T> {
    void validate(T toValidate) throws ValidationException;
}

将使您能够编写可以验证任何类T并且非常可测试的类。您的验证器将如下所示:

class EmptyStringValidator implements Validator<String> {
    public void validate(String toValidate) {
        if(toValidate == null || toValidate.isEmpty()) throw new ValidationException("empty!!!");
    }
}

你可以很容易地测试它。 实际上,如果您使用的是Java 8,那么这将是一个功能接口,因此单个实​​用程序类可以托管多个验证器:

class ValidationUtil {
    public static void emptyString(String val) // same code as above
}

ValidationUtil::emptyString将实施Validator<String>。 您可以将多个验证器与复合模式组合在一起。

如果你需要的话,你也可以有一个带状态的验证器......

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;
    }
}

您可以使用它来验证列表:

List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);

答案 2 :(得分:-1)

当然,这取决于具体情况,但我认为你的直觉是正确的。这种设计可能更加面向对象。

这不仅仅是Validator没有状态,这是一个纯粹的机械指标,它可能不是一个正确的抽象,但名称本身告诉我们一些东西。通常Validator(或甚至EmptyStringValidator)不属于问题域。当你必须创造纯粹技术性的东西时,这总是一个不好的迹象(虽然有时它不是两个邪恶)。

我假设您没有编写Web框架,您正在尝试编写具有某个域的应用程序。例如,它有用户注册。然后,RegistrationForm是问题域的一部分。用户知道关于“注册表”,您可以谈论它,他们会知道您的意思。

在这种情况下,面向对象的验证解决方案是该对象负责在“提交”自身期间验证自身。

public final class RegistrationForm extends Form {
    ...
    @Override
    public void submit() {
        // Do validation here
        // Set input fields to error if there are problems
        // If everything ok do logic
    }
}

我知道这不是Web框架通常看到甚至支持的解决方案。但它面向对象解决方案的样子。

始终牢记的两个要点是:

  1. 不要从对象“获取”数据,要求他们做某事。这与其他任何内容一样适用于UI代码。
  2. 当对象关注有意义的事物,即问题域时,OO是有意义的。避免过度表示技术(不重要)对象,例如Validator(如果那不是您的应用程序的域)。
相关问题