我有一个基类
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类还包含允许以下操作的方法:
查询它包含哪些具体的东西,例如
public Set<Class<? extends AbstractThing>> containsTypes();
获取特定具体类型的事物的子集,例如
public <S extends AbstractMeasurement> Set<S> getSubset(Class<S> type);
目前,我的ThingCollector
实现包含一个类型为Set<AbstractThing>
的私有字段。add(...)
方法将所有内容添加到同一Set对象中。containsTypes()
和getSubset(...)
方法在对集合进行迭代时使用反射来编织它们的魔力。
这很管用,但看起来很乱我相信一定有更好的办法!
你能建议我构建解决方案的其他方法吗我确实考虑过让ThingCollector
为每个扩展AbstractThing
的单独类型维护一个单独的集合,但是:
这意味着
ThingCollector
可能包含数十个Set对象。在大多数用例中,几乎所有这些集合都是空的。尽管有几十种物质继承自AbstractThing
,但在实践中,任何给定的ThingCollector
中都只包含几种不同类型的物质。它也很乱;每次在
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();
}
}));
}
免责声明:示例未经测试。