【问题标题】:Design pattern for creating multiple objects of the same type创建多个相同类型对象的设计模式
【发布时间】:2015-03-24 13:52:12
【问题描述】:

我正在编写一个搜索解析器。有一个输入搜索查询(字符串)需要转换为单个条件对象。

例如,/perons/?q=age>50&name:mike

此查询将转换为两个条件对象。 1.GreaterThanCondition(字符串字段,int值) 2.LikeCondition(字符串字段,字符串值)

我有 14 个实现条件接口的此类条件对象。

在运行时,我从查询中解析出字符串条件(如“age>50”),我需要设计一种算法来有效地将这个条件转换为适当的对象(如 GreaterThanCondition)。

这是我在想的一个算法:创建一个 ConditionFactory。如果工厂中定义的正则表达式(例如,GreaterThanConditionFactory 的正则表达式可以是 [ a-zA-Z0-9]+>+[0-9]+ . GreaterThanConditionFactory 基于正则匹配,可以从条件中识别字段(年龄)和值(50)并创建GreaterThanConditionObject。

使用这种方法,我需要创建 15 个工厂和 14 个条件对象。 我不确定创建那么多工厂是否是一个好的解决方案。 请提出建议。

【问题讨论】:

  • 为什么每个条件都需要 1 个工厂?此外,听起来您已经创建了一个责任链工厂......这听起来不像是一个可怕的想法。
  • @Elliott 如果我把所有东西都放在我的单个工厂中,那么我的 ConditionFactory 中就会有太多的逻辑和太多的 if else 条件。例如,代码看起来像:if("age>50 ").matches(GreaterThanConditionRegex) { 查找字段和值;创建 GreaterThanConditon 对象; } 其他 { .. }
  • 考虑Builder,而不是单个工厂。你的逻辑将不得不去某个地方。
  • 那么对于每个正则表达式,你想触发一个返回条件的算法吗?难道你不能使用某种映射系统,将每个正则表达式映射到一个对象,该对象包含一个处理完整字符串并返回条件的方法?
  • @ManpreetSingh 在 ConditionFactory 中使用 if-else 来确定具体的实现并没有错。工厂背后的整个想法是在一个地方创建所有对象,以便维护变得容易。因此,一个工厂就足够了。此外,您为什么不将其作为参数传递给 GreaterThanConditon 构造函数并让 GreaterThanConditon 类负责将字符串解析为字段和值,而不是在工厂中查找字段和值?让工厂专注于创建对象,让具体实现专注于解析

标签: java algorithm parsing design-patterns factory-pattern


【解决方案1】:

您可以使用一个非常简单的recursive descent parser,它利用了CharacterIterator,以及一个builder。这将更具可读性,比检查 14 个正则表达式更快,并且支持多个查询条件。

public class QueryParser {
  CharacterIterator iterator;
  QueryBuilder queryBuilder;
  QueryConditionBuilder queryConditionBuilder;

  public Query parse(String text) {
    iterator = new StringCharacterIterator(text);
    queryBuilder = new QueryBuilder();
    while (hasNext()) {
      queryConditionBuilder = new QueryConditionBuilder();
      conditionSeparator();
      queryCondition();
      queryBuilder.withCondition(queryConditionBuilder.getQueryCondition()); 
    }
    return queryBuilder.getQuery();
  }

  public void conditionSeparator() {
     // if the next character is an &, then advance the iterator
  }

  public void parseQueryCondition() {
    key();
    operator();
    value();
  }

  public void parseKey() {
    // ... keep reading until the next character is not alphabetic
    queryConditionBuilder.withKey(key);
  }

  public void parseOperator() {
    // ... could be as simple as a one character check
    queryConditionBuilder.withOperator(operator);
  }

  public void parseValue() {
    // ... probably a number, so just read until the next character is not a digit or you reach the end of a string
    queryConditionBuilder.withValue(value);
  }

  public Character peek() {
     // delegate to character iterator
  }

  public Character next() {
     // delegate to character iterator
  }

  public boolean hasNext() {
     // delegate to character iterator
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多