Фильтрация коллекции унаследованных объектов - PullRequest
2 голосов
/ 23 марта 2012

У меня есть базовый класс

public abstract AbstractThing { };

И множество классов, которые наследуют его

public ThingA extends AbstractThing { };
public ThingB extends AbstractThing { };
...
public ThingY extends AbstractThing { };

У меня есть объект ThingCollector, который содержит набор объектов Thing, т.е.:

public class ThingCollector {
  public void add(AbstractThing newThing);
}

Класс ThingCollector также содержит методы, которые позволяют:

  1. Запрос, какие конкретные вещи он содержит, например,

    public Set<Class<? extends AbstractThing>> containsTypes();

  2. Получение подмножества вещей определенного конкретного типа, например

    public <S extends AbstractMeasurement> Set<S> getSubset(Class<S> type);

На данный момент мой *Реализация 1029 * содержит закрытое поле типа Set<AbstractThing>.Метод add(...) добавляет все к этому же объекту Set.Методы containsTypes() и getSubset(...) сплетают свою магию с помощью отражения, перебирая множество.

Это работает, но кажется грязным. Я убежден, что должен быть лучший способ!

Можете ли вы предложить другие способы структурирования своего решения? Я действительно рассматривал вопрос о том, чтобы ThingCollector поддерживал отдельный Набор для каждого отдельного типа, который расширяет AbstractThing, но:

  1. Это означает, что ThingCollector потенциально может содержать десятки объектов Set.И в большинстве случаев использования почти все эти наборы будут пустыми.Несмотря на то, что существует семейство из нескольких десятков вещей, которые наследуются от AbstractThing, на практике только несколько различных типов вещей будут содержаться в любом данном ThingCollector.

  2. Это такжебеспорядочный;каждый раз, когда я определяю другой набор в ThingCollector, мне также нужно добавлять новые методы add(ThingZ t) и getThingZSubset().

Есть ли лучший способ? Есть ли здесь шаблон проектирования или другая организация классов, которая могла бы мне здесь помочь? Я не обязан вышеуказанному интерфейсу для запроса и поднабора содержимого ThingCollector - все предложения учтены!

Ответы [ 2 ]

0 голосов
/ 23 марта 2012

Для фильтрации элементов по типу вы можете использовать Guava's Iterables.filter(Iterable, Class), который специально предназначен для этой цели. Предполагая, что ThingCollector содержит Set<AbstractThing> с именем innerSet:

public <S extends AbstractThing> Set<S> getSubset(Class<S> type) {
    return Sets.newHashSet(Iterables.filter(innerSet, type));
}

Что касается реализации containsTypes(), просто выполните итерацию по каждому элементу и вызовите getClass() для него, добавив результат к Set<Class<? extends AbstractThing>>, который возвращается. Или используйте Guava's Iterables.transform(Iterable, Function), если хотите быть модным:

public Set<Class<? extends AbstractThing>> containsTypes() {
    return Sets.newHashSet(Iterables.transform(
          innerSet,
          new Function<AbstractThing, Class<? extends AbstractThing>>() {
              @Override
              public Class<? extends AbstractThing> apply(AbstractThing thing) {
                  return thing.getClass();
              }
          }));
}

Отказ от ответственности: примеры не проверены.

0 голосов
/ 23 марта 2012

Как насчет использования Map<Class,Set> следующим образом:

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class ThingCollector {

    Map<Class,Set> map = new HashMap<Class,Set>();

    public void add( AbstractThing newThing )
    {
        Class clazz = newThing.getClass();

        Set set = map.get( clazz );
        if ( set == null )
        {
            set = new HashSet();
            map.put( clazz, set );
        }

        set.add( newThing );
    }

    public <S extends AbstractThing> Set<S> getSubset( Class<S> type )
    {
        return map.get( type );
    }
}

Бонусные баллы за использование Гуава Мультикарта, чтобы сделать вашу жизнь еще проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...