没有instanceof的Typesafe委派

时间:2011-06-13 11:59:41

标签: java delegation

我有一个服务程序:

filter(List<Criterion> criteria);

是否有一种很好的方法内部将方法调用分派给特定Criteria的类型安全实现,而不涉及instanceof且不会使API混乱。

我喜欢以下内容(虽然自然不起作用):

filter(List<Criterion> criteria) {
   for (Criterion c : criteria) {
       dispatch(c);
   }
 }

dispatch(FooCriterion c) {...}
dispatch(BarCriterion c) {...}

4 个答案:

答案 0 :(得分:4)

听起来您想使用visitor pattern

维基百科文章包含一个Java示例。

答案 1 :(得分:3)

虽然它可能被视为混乱,但可以使用类似访问者模式(使用双重调度原则):

public class Dispatcher {
    void dispatch(FooCriterion foo) { .. }
    void dispatch(BarCriterion bar) { .. }
}

class FooCriterion implements Criterion {
   void visit(Dispatcher d) {
      d.dispatch(this);
   }
}

Dispatcher d = new Dispatcher();
for (Criterion c : criteria) {
   c.visit(d);
}

答案 2 :(得分:0)

如果您希望根据对象的类型调用该方法的一个且只有一个实例,则访问者模式是首选解决方案。

但是,如果您有C继承B继承A并且您希望对象为其类类型调用方法并且所有继承(例如),则必须使用isAssignableFrom(...)

例如,如果您的对象属于B类,并且您希望它调用dispatch(B obj)dispatch(C obj),则需要分别将这些调用括起来:

if (A.isAssignableFrom(obj.getClass())) { dispatchA(obj); }
if (B.isAssignableFrom(obj.getClass())) { dispatchB(obj); }
if (C.isAssignableFrom(obj.getClass())) { dispatchC(obj); }

不要使用instanceof,因为在这种情况下它不起作用。

答案 3 :(得分:0)

I have only this to suggest with some duplication.
private void filter(List<Criterion> criteria) 
{
 for(FooCriterion c : fetchFooCriterias(criteria))
 {
  dispatch(c);
 }
}
private List<FooCriterion> fetchFooCriterias(List<Criterion> criteria) 
{
 List<FooCriterion> fc = new ArrayList<FooCriterion>();
 for(Criterion c:criteria)
 {
  if(c instanceof BarCriterion)
  {
   fc.add((FooCriterion)c);
  }
 } 
 return fc;
}

另一种解决方案可能是使用以下公共类,但它可能会使您的代码混乱。 import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator;

尝试一下。