筛选继承对象的集合



我有一个基类

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);

目前,我的ThingCollector实现包含一个类型为Set<AbstractThing>的私有字段。add(...)方法将所有内容添加到同一Set对象中。containsTypes()getSubset(...)方法在对集合进行迭代时使用反射来编织它们的魔力。

这很管用,但看起来很乱我相信一定有更好的办法!

你能建议我构建解决方案的其他方法吗我确实考虑过让ThingCollector为每个扩展AbstractThing的单独类型维护一个单独的集合,但是:

  1. 这意味着ThingCollector可能包含数十个Set对象。在大多数用例中,几乎所有这些集合都是空的。尽管有几十种物质继承自AbstractThing,但在实践中,任何给定的ThingCollector中都只包含几种不同类型的物质。

  2. 它也很乱;每次在ThingCollector中定义另一个Set时,我还需要添加新的方法add(ThingZ t)getThingZSubset()

有更好的方法吗<有没有设计模式或不同的班级组织可以帮助我>我不感谢上面的界面查询和子设置ThingCollector的内容-所有建议都考虑在内!

按如下方式使用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 );
    }
}

使用Guava Multimap使您的生活更加轻松,可获得额外积分。

对于基于类型的过滤元素,您可以使用Guava的Iterables.filter(Iterable, Class),这是专门用于此目的的。假设ThingCollector包含一个名为innerSet:的Set<AbstractThing>

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

至于实现containsTypes(),只需对每个元素进行迭代,并对其调用getClass(),将结果添加到Set<Class<? extends AbstractThing>>中,然后返回。或者,如果你想变漂亮,可以使用Guava的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();
              }
          }));
}

免责声明:示例未经测试。

最新更新