依赖顺序验证的设计模式

Design Patterns for dependent sequential validation

我有三个验证器,每个验证器依次依赖于前一个。我可能会使用全部三个或仅使用前两个或仅使用第一个。例如

  1. 验证器 1:检查用户是否存在
  2. 验证器 2:检查请求的订单是否存在于用户的订单历史记录中
  3. 验证器 3:检查该订单是否有取消选项

如果不满足先前的条件,此列表中的每个验证器都会抛出错误。我目前正在使用这种模式:

function validator1() { ... }

function validator2() { validator1(); ... }

function validator3() { validator2(); ... }

但这对我来说感觉像是一种反模式,因为所有先决条件验证都是隐式完成的,所以当我 运行 validtor2() 时,不清楚 validator1() 是否也在 运行.

我也考虑过这样做:

function validator1() { ... }

function validator2() { ... }

function validator3() { ... }

function someTask() { validator1(); validator2(); validator3(); ... }

但这是不安全的,因为没有什么可以阻止我 运行ning validator3() 并在不满足条件 2 时抛出错误。

有没有一种既安全又明确的方法来做到这一点?

编辑

对于接受的答案中提到的设计模式,这是一个很好的参考:https://refactoring.guru/design-patterns/chain-of-responsibility

我建议查看 责任链Builder 模式 特定于验证。 看这里:

您还可以查看装饰器模式的用法:

Is there a way to do this that is both safe and explicit?

但在考虑其中一种模式当然可能提供更多灵活性但也更复杂的模式之前,请考虑您的规则是否真的可以扩展很多并且将被重用以及那么多情况。否则,立即采用建议的模式之一可能有点过度工程。

此外,您可以通过使用有意义的函数名称明确告诉代码的 reader 正在执行什么特定用例,从而使很多内容更加明确。这样的功能更像是所需验证步骤的协调器。所以你的方法(尽管名字不好 someTask())可能已经满足你的需要。

But this is unsafe because there is nothing stopping me from running validator3() and throwing an error if condition 2 hasn't been met.

如果其中一个验证失败,您可以让每个验证异常都抛出一个异常,或者引入具有主要任务 return 的保护子句。

另一种选择是传入或注册具有相同接口的验证列表,然后将它们循环通过。如果您需要检查所有验证并收集每个验证步骤的结果(例如错误代码或消息)或在第一次验证时抛出异常,则满足您的需要。