2012-03-23 103 views
2

我有一个基类过滤继承的对象

public abstract AbstractThing { }; 

而且大量的类继承它的集合

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

我有一个ThingCollector对象,它包含了一组事的对象,即:

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(...)方法在迭代Set时使用反射来编织它们的魔法。

这工作,但它似乎凌乱。我确信必须有更好的方法!

你能否提出其他方法来构建我的解决方案?我确实认为有ThingCollector维护一个单独设置的扩展AbstractThing每个单独的类型,但:

  1. 这将意味着ThingCollector将可能包含几十集的对象。而在大多数使用情况下,几乎所有这些设置都是空的。即使有一个由AbstractThing继承的几十件东西的家族,实际上在任何给定的ThingCollector中只有几种不同类型的东西会包含在内。

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

有没有更好的方法? 有没有可能帮助我的设计模式或不同的班级组织?我不赞成上面的界面查询和子集ThingCollector的内容 - 所有建议都考虑到了!

+0

我也应该加上......虽然第三方库(如建议的番石榴)确实存在,但我想避免在这种情况下使用它们。 – turingbot 2012-03-23 04:24:56

+0

你应该展示你的实现代码 - “使用反射来编织他们的魔法”还不足以让我们知道什么可以改进。 – 2012-03-23 18:24:04

回答

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之,以使您的生活更轻松加分。

+0

谢谢。这与我现在执行的实现非常相似,这让我相信这是一个很好的方法。 不幸的是,在工作中跳过太多的箍以获得批准使用像番石榴这样的第三方库,即使它们是开源的。 – turingbot 2012-03-23 04:22:45

0

对于基于类型的过滤元素,可以使用Guava的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>>,它被返回。

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

免责声明:例子是未经检验或者,如果你想成为幻想用番石榴的Iterables.transform(Iterable, Function)