我有一个服务程序:
filter(List<Criterion> criteria);
是否有一种很好的方法内部将方法调用分派给特定Criteria
的类型安全实现,而不涉及instanceof
且不会使API混乱。
我喜欢以下内容(虽然自然不起作用):
filter(List<Criterion> criteria) {
for (Criterion c : criteria) {
dispatch(c);
}
}
dispatch(FooCriterion c) {...}
dispatch(BarCriterion c) {...}
答案 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;
尝试一下。