Java设计模式:强制所有超类型的调用方法

时间:2015-07-26 14:47:30

标签: java inheritance class-hierarchy call-hierarchy

简介:

我为数据库过滤器构建了一个类层次结构:

class Filter {
}

class PropertyFilter<T> extends Filter {
  Boolean exists;
  T equal;
}

class ComparableFilter<T> extends PropertyFilter<T> {
  T greaterThan;
  T lessThan;
}

这样我可以使用PropertyFilter<String>表示字符串,ComparableFilter<DateTime>表示DateTime对象。

棘手的部分:

我有一些过滤器查询构建器,它遵循与过滤器类相同的层次结构。查询构建器的每一方都应仅添加其他查询。

示例:

class FilterQueryBuilder<T extends Filter> {
  protected final T filter;      

  public FilterQueryBuilder(T filter) {
    this.filter = filter;
  }

  public Query getQuery() {
    return new Query();
  }
}

class PropertyFilterQueryBuilder<T extends PropertyFilter<?>> extends FilterQueryBuilder<T> {
  public PropertyFilterQueryBuilder(T filter) {
    super(filter);
  }

  public Query getQuery() {
    Query query = super.getQuery();
    if(filter.exists != null) addExistsQuery(query, filter.exists);
    if(filter.equal != null) addEqualQuery(query, filter.equal);
    return query;
  }
}

class ComparableFilterQueryBuilder<T extends ComparableFilter<?>> extends PropertyFilterQueryBuilder<T> {
  public ComparableFilterQueryBuilder(T filter) {
    super(filter);
  }

  public Query getQuery() {
    Query query = super.getQuery();
    if(filter.greaterThan != null) addGreaterThanQuery(query, filter.greaterThan);
    if(filter.lessThan != null) addLessThanQuery(query, filter.lessThan);
    return query;
  }
}

问题/疑问:

如您所见,我总是要调用super.getQuery()然后返回修改后的查询对象。

如果每个类只有addFiltersToQuery这样的方法会更容易:

addFiltersToQuery() {
  if(filter.x != null) addXQuery(query, filter.x);
  if(filter.y != null) addYQuery(query, filter.y);
}

但是我当然会用我的类层次结构覆盖这个方法。虽然如果我在addFiltersToQuery类中调用FilterQueryBuilder,我只会获得最新的实现。

有没有办法在不使用super的情况下调用所有实现?

1 个答案:

答案 0 :(得分:0)

我现在已经建立了一些方法来解决这个问题:

class FilterQueryBuilder<T extends Filter> {
  private final T filter;
  private List<Consumer<Query>> queryConsumers = new ArrayList<>();

  public FilterQueryBuilder(T filter) {
    this.filter = filter;
  }

  protected void addQueryConsumer(Consumer<Query> consumer) {
     queryConsumers.add(consumer);
  }

  public Query getQuery() {
    Query query = new Query();
    queryConsumers.forEach(c -> c.accept(query));
    return query;
  }
}

class PropertyFilterQueryBuilder<T extends PropertyFilter<?>> extends FilterQueryBuilder<T> {
  public PropertyFilterQueryBuilder(T filter) {
    super(filter);
    addQueryConsumer(query -> {
      if(filter.exists != null) addExistsQuery(query, filter.exists);
      if(filter.equal != null) addEqualQuery(query, filter.equal);
    });
  }
}

class ComparableFilterQueryBuilder<T extends ComparableFilter<?>> extends PropertyFilterQueryBuilder<T> {
  public ComparableFilterQueryBuilder(T filter) {
    super(filter);
    addQueryConsumer(query -> {
      if(filter.greaterThan != null) addGreaterThanQuery(query, filter.greaterThan);
      if(filter.lessThan != null) addLessThanQuery(query, filter.lessThan);
    });
  }
}

每个类将其查询添加内容写入queryConsumers数组,FilterQueryBuilder类适用于所有这些使用者。