我正在编写一个新的应用程序,使用Guice进行依赖注入,以及Guava的属性验证前置条件。
我使用工厂模式根据外部输入创建bean。问题是,验证输入的首选方法是什么?(在可维护性,清晰度等方面)
让我们假设这些课程:
Bean.java
public interface Bean {
public Object getFoo();
}
BeanImpl.java
public class BeanImpl implements Bean {
private final Object foo;
public BeanImpl(Object param) {
foo = param;
}
@Override
public String getFoo() {
return foo;
}
}
我想查看" param"持有" foo"的有效值:
Preconditions.checkArgument(SomeValidator.isValid(param), "Bad param: %s!", param);
我应该在哪里做以及为什么?
答案 0 :(得分:4)
如果构造具有特定BeanImpl
值的foo
无效,则在构造函数中抛出IllegalArgumentException
,详细说明错误。
public class BeanImpl {
...
public BeanImpl(Object param) {
if (param == null) {
throw new IllegalArgumentException("Param cannot be null");
}
foo = param;
}
...
}
从对象的早期定义是"状态和行为结合"这强制您不会污染具有无效状态的对象。
就工厂而言,在构建物体之前检查数值是一种方便,但工厂的真正责任并未延伸到对象的责任范围内。工厂模式有助于确保对象以有意义的方式与其他对象相对应,但它不应该完成对象的工作,以确保对象的内部状态是正确的。
让一个Object(工厂)确保另一个Object的状态是正确的是错位的行为。您将行为(验证状态)放在Factory中,但状态在Object中。因此,您现在拥有分散的连接代码,应该紧密耦合。这意味着现在你必须有一个工厂来制作一个对象,而不是让工厂在有意义的时候制作一个对象,并在它没有时直接制作对象。
这经常出现在单元测试中。如果您没有将验证码放在工厂中,您可以单独对对象进行单元测试;测试不良参数。但是,如果您将验证码放在工厂中,您将无法构建"有效"没有工厂的物体,这是你得到的第一个提示,你不自然地耦合了两个不应该紧密耦合在一起的物体。
当然,也有例外;但是当人们期望数据是正确的时,他们往往会来,但收集数据的方式并没有提供验证。例如,由于从网络套接字收集的结构化记录实际上可能具有在概念上内部不一致的数据;但是,由于处理的性质,处理,记录和丢弃无效输入。
答案 1 :(得分:-1)
从Netflix查看Guvernator框架:
https://github.com/Netflix/governator/wiki/Field-Validation
它构建于Google Guice之上,并通过一些很酷的功能扩展它,例如
在你的项目中还有更多的锅炉板包括guvernator,但绝对值得尝试。