8

在使用工厂模式时,工厂本身是否应该包含验证逻辑,还是应该留给调用类在传递上下文数据之前处理验证?

我有一个简单的工厂方法,但它依赖于传递给它的配置树来决定要实例化的对象。

可能存在配置 xml 格式正确的情况,但不是工厂期望的正确格式,我不知道应该在哪里验证。

4

3 回答 3

3

在使用工厂模式时,工厂本身是否应该包含验证逻辑,还是应该留给调用类在传递上下文数据之前处理验证?

组织验证有两种不同的选择:

  1. 验证作为一个单独的过程

有一个单独的验证方法Validate(Config)。该方法在构造方法之前调用,返回信息是否Config有效。如果Validate方法返回Config有效,则调用构造方法。构建过程中的任何错误都被视为异常。

  1. 验证作为施工过程的一部分

没有单独的验证方法。而是在需要时在构造方法内部进行验证。允许构造方法失败并返回构造对象或指示错误的结果。

第二个变体可以使用 monad 很好地实现,代码和性能开销几乎为零。

于 2016-01-02T13:49:20.677 回答
3

你说的验证是什么意思?是什么让您认为作为工厂设计模式实例的一部分的代码与任何其他代码不同?

如果验证是指检查从用户或输入文件读取的输入值,答案是否定的:解析输入的代码负责验证,而不是随后使用读取值的工厂。

如果通过验证您的意思是让 Factory 的工厂方法检查其调用者提供的值是否符合这些方法的先决条件,那么答案与对其参数施加先决条件的任何其他方法相同:Java 的共识风格用于检查其先决条件并在RuntimeException不满足先决条件时抛出合适的方法。

现在,在实践中,这意味着某些输入值将被检查两次。首先是输入验证码,然后是工厂的前置条件检查。部分原因是将代码分解为模块(这里是单独的输入模块和服务层)的成本。

但它也允许检查以不同的方式报告,这更适合他们的目的。

  • 失败的前置条件检查(在本例中为工厂)表明程序中存在错误。我们希望在程序状态改变之前快速而准确地报告前置条件失败,以获得最有用的调试信息(在许多情况下,错误的位置将是调用堆栈中的一个方法)。
  • 对于输入验证失败,我们通常希望程序在输入的一次解析中报告尽可能多的错误,以便用户可以修复所有错误。想想你使用的编译器:如果它在你的源代码中发现第一个语法错误后停止,你会感到沮丧。抛出异常来实现这一点是不合适的。如果可能,代码应该记录错误并继续解析,而不是在程序中弹出到更高级别的部分(这是引发异常的原因)。
于 2016-01-02T19:07:27.367 回答
2

为什么不两者都提供?有了这个,你将责任传递给调用者,即他是否希望他的输入得到验证。

以 Apache Commons 为例 - InstantiateFactory

它的默认构造函数不提供验证:

InstantiateFactory(java.lang.Class classToInstantiate)

不执行验证的构造函数。

但提供验证getInstance

静态工厂getInstance (java.lang.Class classToInstantiate, java.lang.Class[] paramTypes, java.lang.Object[] args)

执行验证的工厂方法。

于 2013-04-25T18:03:14.193 回答