Type delegation without instance

I have a utility program:

filter(List<Criterion> criteria);

Is there a good way to internally send a method call to a typical implementation of a concrete Criteriawithout involving instanceofand without cluttering the API.

I would like something like the following (which naturally does not work):

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

dispatch(FooCriterion c) {...}
dispatch(BarCriterion c) {...}
+3
source share
4 answers

Although this can be seen as a clutter, you can use something like the Visitor template (using the principle of double sending):

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);
}
+3
source

It looks like you want to use a template.

The wikipedia article contains a Java example.

+4
source

, , .

, B A, , (), IsAssignableFrom (...).

For example, if your object exists, if type B and you want it to call dispatch(B obj)and dispatch(C obj), you need to make these calls accordingly:

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

Never use instanceof, because in this case it will not work.

0
source
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;
}

Another solution might be to use the following commons classes, but this can clutter up your code. import org.apache.commons.collections.Predicate; import org.apache.commons.collections.iterators.FilterIterator;

Give it a try.

0
source

All Articles