You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需分支语句为Feature子类调用对应filterPredicates重载方法?

解决方案

你的核心问题是Java方法重载是编译期静态绑定,所以直接传递Feature类型的变量无法自动匹配子类对应的filterPredicates重载方法。要实现运行时根据实际子类型调用对应方法,同时避免手动编写大量if/else或switch,可以用以下两种方案:

方案一:访问者模式(通用兼容方案)

这是处理这种多态分发场景的经典设计模式,符合开闭原则——后续新增Feature子类时,不需要修改原有循环逻辑,只需要扩展访问者相关代码。

步骤1:定义访问者接口

创建一个接口,包含对应每个Feature子类的处理方法:

interface FeatureVisitor {
    ArrayList<Predicate> visit(NPC npc, ArrayList<Predicate> predicates);
    ArrayList<Predicate> visit(Settlement settlement, ArrayList<Predicate> predicates);
    // 新增Feature子类时,在这里添加对应的visit方法
}

步骤2:在父类Feature中添加抽象的accept方法

让父类定义接受访问者的规范,强制子类实现:

public abstract class Feature {
    public abstract ArrayList<Predicate> accept(FeatureVisitor visitor, ArrayList<Predicate> predicates);
}

步骤3:子类实现accept方法

每个子类将自身实例传递给访问者的对应方法,完成类型分发:

public class NPC extends Feature {
    @Override
    public ArrayList<Predicate> accept(FeatureVisitor visitor, ArrayList<Predicate> predicates) {
        return visitor.visit(this, predicates);
    }
}

public class Settlement extends Feature {
    @Override
    public ArrayList<Predicate> accept(FeatureVisitor visitor, ArrayList<Predicate> predicates) {
        return visitor.visit(this, predicates);
    }
}

步骤4:实现访问者类,封装过滤逻辑

把原来的filterPredicates逻辑迁移到访问者的实现类中:

private class PredicateFilterVisitor implements FeatureVisitor {
    @Override
    public ArrayList<Predicate> visit(NPC npc, ArrayList<Predicate> predicates) {
        // 原filterPredicates(NPC, ...)的过滤逻辑
        ArrayList<Predicate> filteredPredicates = new ArrayList<>();
        // 这里编写NPC专属的Predicate过滤逻辑
        return filteredPredicates;
    }

    @Override
    public ArrayList<Predicate> visit(Settlement settlement, ArrayList<Predicate> predicates) {
        // 原filterPredicates(Settlement, ...)的过滤逻辑
        ArrayList<Predicate> filteredPredicates = new ArrayList<>();
        // 这里编写Settlement专属的Predicate过滤逻辑
        return filteredPredicates;
    }
}

步骤5:修改generateNewRelationships方法

使用访问者完成动态调用:

public ArrayList<Relationship> generateNewRelationships(ArrayList<Feature> features) {
    FeatureVisitor filterVisitor = new PredicateFilterVisitor();
    for(Feature feature : features) {
        ArrayList<Predicate> possiblePredicates = feature.accept(filterVisitor, subjectPredicates);
        // 后续处理逻辑
    }
    return new ArrayList<>();
}

方案二:Java 16+ 模式匹配(简化方案)

如果你的项目使用Java 16及以上版本,可以利用原生的switch模式匹配,代码更简洁,不需要额外的接口和类:

直接修改generateNewRelationships方法:

public ArrayList<Relationship> generateNewRelationships(ArrayList<Feature> features) {
    for(Feature feature : features) {
        ArrayList<Predicate> possiblePredicates = switch(feature) {
            case NPC npc -> filterPredicates(npc, subjectPredicates);
            case Settlement settlement -> filterPredicates(settlement, subjectPredicates);
            // 新增Feature子类时,只需添加对应的case分支
            default -> throw new IllegalArgumentException("不支持的Feature类型: " + feature.getClass());
        };
        // 后续处理逻辑
    }
    return new ArrayList<>();
}

方案对比

  • 访问者模式:适合需要频繁扩展子类、且希望核心循环逻辑完全不修改的场景,代码结构更清晰,但需要额外定义接口和类。
  • Java 16+模式匹配:代码量少、实现简单,新增子类时仅需添加case分支,维护成本低,适合中小规模的项目场景。

内容的提问来源于stack exchange,提问作者Luke Burston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:48:21