我会将意图抽象化,这样它的实现方式或源代码的组织方式并不重要。在基本层面上,您拥有的是一组检查器,它们生成一组故障解释。
伪代码基本上是:
let reasons be a new, empty collection of failure reasons
let checkers be the list of relevant checkers
for each checker in checkers
if checker passes, continue
if checker fails, add explanation to reasons
if number of reasons is zero,
voucher is valid, success
if number of reasons > zero,
the voucher is invalid, format each element in reasons for display to the user
有了这个逻辑,检查器的组织方式并不重要,只要它们可以通过列表中的这部分代码获得即可。您可以有一个带有许多检查的方法,可能会添加许多原因。您可以有许多类,在检查器列表中每个类都有一个实例。至关重要的是,实际的检查器与此逻辑解耦,可以随时使用不同的检查器(想想业务规则的变化,或者不同区域的不同规则)。
根据您的语言,这将至少涉及抽象用于检查器的类型。
从那开始。如果您发现相同的数据库查询,请开始考虑为检查器集合的运行使用缓存。
至于检查器是如何在源代码级别组织的......这并不重要。只有抽象可以。一旦提供了可以隐藏的抽象级别,细节就相当灵活。
优点:
- 执行检查的位不关心实际的具体检查(可能会根据业务规则而改变)。
- 可以根据您的喜好组织检查器:在一个源文件中一起定义,或根据其他方案展开。它还允许自由地分离出单个检查器进行测试。
- 无论检查的类型或数量如何,集合和漂亮的格式只需要实现一次。
缺点:
- 提前做好抽象设计的体面工作需要时间。这可能会在以后得到回报。
- 有一层间接性可能会使其更难理解,也难以追踪正在进行的实际检查。灵活性会损害可理解性。这些是您必须为您的方案考虑的事情。在我看来,代金券的规则似乎会随着时间的推移而改变,这里的抽象并不难理解,所以我认为这是值得的。
我花时间用 Java 编写了一个示例,但它确实没有增加多少。如果您尝试从抽象的角度进行思考,那么实际的机制就不那么重要了。