1

序章:

データベース フィルターのクラス階層を作成しました。

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か?

4

1 に答える 1

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クラスはそれらすべてのコンシューマーを適用します。

于 2015-07-27T10:15:21.780 に答える