【问题标题】:Iterating through strategy design pattern迭代策略设计模式
【发布时间】:2012-08-22 18:20:19
【问题描述】:

我有一个要在数据集上运行的算法列表。例如,假设我的数据集是地址列表。我需要检查地址的有效性,但我有几种不同的验证算法。假设我有validation_onevalidation_two。但将来我需要添加validation_threevalidation_four 等。我需要在地址列表上运行所有验证,即使是新添加的验证。

是否有适合此的设计模式?我知道策略是选择一种算法,但我特别需要一种将所有算法应用于数据集的方法。

【问题讨论】:

    标签: asp.net ruby algorithm design-patterns strategy-pattern


    【解决方案1】:

    你没有说一种语言..但假设它有泛型。

    给定一个DataSet<T>

    还假设不需要交叉验证(即每个 T 都可以完全通过自己的数据进行验证)

    使用单一方法声明验证策略。

    IValidate<T>{bool validate(T item);} 
    

    validation_one,validation_two…。将执行此策略

    有一个List&lt;IValidate&lt;T&gt;&gt;,您可以在其中添加和删除实现。

    数据集中的每个项目调用列表中的每个策略。

    然后,您可以选择如何处理失败。

    【讨论】:

    • 我做过这种事情,我唯一要添加到@yoztastic 所说的是(在生产代码中)通过提供额外的错误详细信息来使验证方法更加冗长.您通常不想知道数据集是否失败,您想返回一个列表,了解哪些行失败,哪些规则或哪些规则导致失败,以及人类可读的消息。 “‘XYZ’字段无效。错误是‘超出范围’。原因是‘该字段必须大于 0 且小于 365’。”只是一个建议,但在一开始就建立对此的支持!
    • 完全同意@tcarvin。我将填充一个 Map> ,其中列表包含每个策略失败的人类可读解释。地图中未找到的任何 T 均因缺失而有效。
    • 这是一个实现细节,但我创建了一个错误集合并将其作为验证签名的一部分传递。对于任何验证错误,Validate 方法实现添加了一个错误对象来存储这些详细信息。要查看整个操作是否被验证干净,它就像if (errors.Count == 0) 一样简单。通过将错误集合转储到网格中,也可以轻松地向用户展示所有错误细节。
    【解决方案2】:

    这听起来像责任链,链中的所有处理程序都接受请求并将其传递给下一个处理程序。

    【讨论】:

    • ...这是一种堆肥。参见en.wikipedia.org/wiki/Composite_pattern 注意,Component 接口作为一个 operation() 定义。
    • 责任链不是复合模式。复合模式总是暗示父/子对象的树结构符合相同的接口,其中客户端仅对父对象进行调用。例如,View、Pane 和 Widget 类都可以使用 Draw() 方法实现 Drawable 接口。单个视图可以组成多个窗格,这些窗格可以组成其他窗格,这些窗格可以组成小部件。客户不在乎树有多大。它只是调用 viewInstance.Draw() 来绘制自己并指示它的每个孩子绘制自己,等等。
    【解决方案3】:

    Composite.

    这基本上是其他两个答案等同的。

    第一个答案是复合材料的实现。第二种是使用责任链作为组合。

    【讨论】:

    • 不,它不仅仅是复合。复合是一种结构模式,它以树状结构组织对象。没有“处理”树的概念,您需要像访客这样的附加模式来引入“处理”。如果没有提及访客,则您的答案是不完整的。另一方面,响应链是一种行为模式,它是围绕处理程序处理请求的概念建立的。问候。
    • Composite 绝对是一种处理组合中相似类型项目的树(或列表)的方法。为什么还有复合材料?仅当您想在组合中注入算法时才使用访问者。复合通常被归类为结构模式,但核心概念是您可以使许多行为像一个 - 在结构上和行为上。响应链。与 Composite 的主要区别在于消息/请求的条件转发和可选的延迟处理。
    • 复合模式是一种结构组织,其中用于组成单个对象的所有项都符合树结构中的相同接口。循环遍历所有符合接口的项目集合并调用方法不是复合模式。