2

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

             解析入口
                 |
                 |
                / \
               / \
              / \
NumericParseEntry StringParseEntry

ETC。,

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

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

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

我能想到的一种粗略的方法是有一个工厂类,它维护解析条目类型与其对应的求值器/SQL 生成器之间的映射。另一种方法是将求值器/sql 生成器作为解析条目的数据成员嵌入,并在 getter 中返回它们。

对此即兴创作的任何帮助将不胜感激。

4

3 回答 3

2

这对我来说听起来像是访客模式。您将拥有EvaluatorVisitorSQLGenerationVisitorwhich 将对 s 进行访问操作ParseEntryParseEntry是一个包含一个操作的元素,该操作将扩展。accept(Visitor)NumericParseEntryStringParseEntry

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

于 2012-07-15T11:07:43.407 回答
1

普通数据对象不是非常面向对象的。我认为操作(评估/生成SQL)确实是ParseEntry对象的责任。如果您想重用评估器实现,您仍然可以编写一个EvaluatorinParseEntry并委托给它,例如:

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
}
于 2012-07-15T04:54:51.080 回答
1

我已经成功地使用这种模式实现复杂案例分析来实现与您尝试做的类似的事情......您将能够以一种优雅的方式创建取决于类型或您选择的任何条件的代码,而无需修改“数据”层次结构。

于 2012-07-15T05:19:13.550 回答