作为解析器库的一部分,我有以下对象层次结构:
ParseEntry | | / \ / \ / \ NumericParseEntry StringParseEntry
等,
这些对象基本上包含数据。然后,我有一组操作,如evaluate(用于评估值是否通过解析条目标准),generateSQL(根据解析条目标准生成SQL条件)。
由于单一责任原则,我不想将这些函数添加到特定的解析条目类中,并且希望维护为解析条目层次结构实现这些函数的单独层次结构。这允许我为多个解析条目重用某个实现。
我想知道如何将操作与对象结合起来,这样当我浏览执行某些操作的解析条目的解析表时,我应该能够获得适当的操作对象。
我能想到的一个原始方法是拥有一个工厂类,它在parse条目类型和相应的赋值器/ SQLgenerator之间维护一个映射。另一种方法是将evaluateator / sql生成器作为解析条目的数据成员嵌入,并在getter中返回它们。
非常感谢任何对此即兴创作的帮助。
答案 0 :(得分:2)
对我来说这听起来像Visitor Pattern。您将EvaluatorVisitor
和SQLGenerationVisitor
在<{1}}上进行访问操作。 ParseEntry
是一个元素,其中包含ParseEntry
和accept(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来实现与您尝试执行的操作类似的操作...您将能够创建依赖于您选择的类型或条件的代码,优雅的方式,无需修改“数据”层次结构。