在使用工厂模式时,工厂本身是否应该包含验证逻辑,还是应该留给调用类在传递上下文数据之前处理验证?
我有一个简单的工厂方法,但它依赖于传递给它的配置树来决定要实例化的对象。
可能存在配置 xml 格式正确的情况,但不是工厂期望的正确格式,我不知道应该在哪里验证。
在使用工厂模式时,工厂本身是否应该包含验证逻辑,还是应该留给调用类在传递上下文数据之前处理验证?
我有一个简单的工厂方法,但它依赖于传递给它的配置树来决定要实例化的对象。
可能存在配置 xml 格式正确的情况,但不是工厂期望的正确格式,我不知道应该在哪里验证。
在使用工厂模式时,工厂本身是否应该包含验证逻辑,还是应该留给调用类在传递上下文数据之前处理验证?
组织验证有两种不同的选择:
有一个单独的验证方法Validate(Config)
。该方法在构造方法之前调用,返回信息是否Config
有效。如果Validate
方法返回Config
有效,则调用构造方法。构建过程中的任何错误都被视为异常。
没有单独的验证方法。而是在需要时在构造方法内部进行验证。允许构造方法失败并返回构造对象或指示错误的结果。
第二个变体可以使用 monad 很好地实现,代码和性能开销几乎为零。
你说的验证是什么意思?是什么让您认为作为工厂设计模式实例的一部分的代码与任何其他代码不同?
如果验证是指检查从用户或输入文件读取的输入值,答案是否定的:解析输入的代码负责验证,而不是随后使用读取值的工厂。
如果通过验证您的意思是让 Factory 的工厂方法检查其调用者提供的值是否符合这些方法的先决条件,那么答案与对其参数施加先决条件的任何其他方法相同:Java 的共识风格用于检查其先决条件并在RuntimeException
不满足先决条件时抛出合适的方法。
现在,在实践中,这意味着某些输入值将被检查两次。首先是输入验证码,然后是工厂的前置条件检查。部分原因是将代码分解为模块(这里是单独的输入模块和服务层)的成本。
但它也允许检查以不同的方式报告,这更适合他们的目的。
为什么不两者都提供?有了这个,你将责任传递给调用者,即他是否希望他的输入得到验证。
以 Apache Commons 为例 - InstantiateFactory
:
它的默认构造函数不提供验证:
InstantiateFactory(java.lang.Class classToInstantiate)
不执行验证的构造函数。
但提供验证getInstance
:
静态工厂getInstance (java.lang.Class classToInstantiate, java.lang.Class[] paramTypes, java.lang.Object[] args)
执行验证的工厂方法。