过滤一组继承的对象

时间:2012-03-23 03:45:14

标签: java oop inheritance collections

我有一个基类

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

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

    这很有效,但看起来很乱。我确信必须有更好的方法!

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

    1. 这意味着ThingCollector可能包含数十个Set对象。在大多数用例中,几乎所有这些集都是空的。尽管从AbstractThing继承了几十件事物的家族,实际上在任何给定的ThingCollector中只会包含几种不同类型的事物。

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

    3. 有更好的方法吗? 是否有可以帮助我的设计模式或不同的类组织?我不会对上面的界面感兴趣,无法查询和对ThingCollector的内容进行子集化 - 所有考虑的建议! / p>

2 个答案:

答案 0 :(得分:0)

如何使用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让您的生活更轻松的好处。

答案 1 :(得分:0)

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

innerSet

至于实现public <S extends AbstractThing> Set<S> getSubset(Class<S> type) { return Sets.newHashSet(Iterables.filter(innerSet, type)); } ,只需迭代每个元素并在其上调用getClass(),将结果添加到containsTypes(),然后返回。或者如果你想要花哨的话,可以使用Guava的Iterables.transform(Iterable, Function)

Set<Class<? extends AbstractThing>>

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