我正在使用工厂模式根据外部输入创建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);
我应该在哪里做,为什么?
>在BeanImpl的构造函数中? (我不确定为什么,但在构造函数中添加检查感觉是个坏主意.)
>在调用beanfactory.create(param)之前? (听起来很糟糕的代码重复.)
>通过一些我不知道的Guice机制?
解决方法
public class BeanImpl { ... public BeanImpl(Object param) { if (param == null) { throw new IllegalArgumentException("Param cannot be null"); } foo = param; } ... }
从对象的早期定义是“状态和行为组合”,这强制您不会污染具有无效状态的对象.
就工厂而言,在构造对象之前检查值是一种方便,但工厂的真正职责并没有扩展到对象的责任.工厂模式有利于确保Object以有意义的方式与其他对象相对应,但它不应该执行Object确保Object的内部状态正确的工作.
让一个Object(工厂)确保另一个Object的状态正确是错误的行为.您将行为(验证状态)放在Factory中,但状态在Object中.结果,您现在拥有了应该紧密耦合的分散连接代码.这意味着现在你必须有一个Factory来创建一个Object,而不是让Factory在有意义的时候创建一个对象,而在没有它时直接创建Object.
这经常出现在单元测试中.如果您没有将验证码放在工厂中,您可以单独对对象进行单元测试;测试不良参数.但是,如果你将验证码放在工厂中,你将无法在没有工厂的情况下构造“有效”对象,这是你得到的第一个提示,你不自然地耦合了两个不应紧密耦合在一起的对象.
当然,也有例外;但是当人们期望数据是正确的时,它们往往会出现,但收集数据的方式并没有提供验证.例如,从网络套接字收集的结构化记录实际上可能具有概念上不符合内部一致性的数据;但是,由于处理的性质,处理,记录和丢弃无效输入.