耦合对象层次结构和操作

时间:2012-07-15 03:10:27

标签: design-patterns

作为解析器库的一部分,我有以下对象层次结构:

             ParseEntry
                 |
                 |
                / \
               /   \
              /     \
NumericParseEntry   StringParseEntry

等,

这些对象基本上包含数据。然后,我有一组操作,如evaluate(用于评估值是否通过解析条目标准),generateSQL(根据解析条目标准生成SQL条件)。

由于单一责任原则,我不想将这些函数添加到特定的解析条目类中,并且希望维护为解析条目层次结构实现这些函数的单独层次结构。这允许我为多个解析条目重用某个实现。

我想知道如何将操作与对象结合起来,这样当我浏览执行某些操作的解析条目的解析表时,我应该能够获得适当的操作对象。

我能想到的一个原始方法是拥有一个工厂类,它在parse条目类型和相应的赋值器/ SQLgenerator之间维护一个映射。另一种方法是将evaluateator / sql生成器作为解析条目的数据成员嵌入,并在getter中返回它们。

非常感谢任何对此即兴创作的帮助。

3 个答案:

答案 0 :(得分:2)

对我来说这听起来像Visitor Pattern。您将EvaluatorVisitorSQLGenerationVisitor在<{1}}上进行访问操作。 ParseEntry是一个元素,其中包含ParseEntryaccept(Visitor)扩展的NumericParseEntry操作。

因为您使用的是访客模式,所以单一责任原则是免费的。

答案 1 :(得分:1)

普通数据对象不是非常面向对象的。我认为操作(evaluate / generateSQL)确实是ParseEntry对象的责任。如果要重用评估程序实现,您仍然可以在Evaluator中编写ParseEntry并委托给它,例如:

public class NumericParseEntry extends ParseEntry {
  private Evaluator evaluator = ...;
  private SQLGenerator sqlGenerator = ...;

  public bool evaluate(Object value) {
    return evaluator.evaluate(this, value);
  }

  public String generateSQL() {
    return sqlGenerator.generateSQL(this);
  }
}

单一责任原则说,只有一个理由可以让课程改变 - 如果你的改变确实与特定的ParseEntry有关,那么改变课程就没有错。


此外,您可以考虑使用继承并完全删除单独的Evaluator / Generator类。例如:

public class NumericParseEntry extends ParseEntry {
  // put common logic for numeric entries here
}

public class IntegerParseEntry extends NumericParseEntry {
  // put specialized code for handling integers
}

public class FloatParseEntry extends NumericParseEntry {
  // put specialized code for handling floating-point
}

答案 2 :(得分:1)

我已成功使用此模式Implementing Complex Case Analysis来实现与您尝试执行的操作类似的操作...您将能够创建依赖于您选择的类型或条件的代码,优雅的方式,无需修改“数据”层次结构。