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

Java8中如何不使用instanceof与访问者模式调用适配Box不同实现类的重载方法

解决方案

问题根源:Java的方法重载是静态分派,只会根据编译期变量类型匹配方法,你声明的变量是Box类型,编译期无法匹配到具体实现类的重载方法,所以会报错。
以下方案不需要修改模型层,也不需要使用instanceof或者访问者模式:

方案:使用类型映射表实现动态派发

思路:在视图层的BoxAdapterToRenderer类内部维护一个「Box实现类 -> 对应渲染构造函数」的映射表,运行时根据实例的实际类型匹配对应的构造逻辑,所有逻辑都收敛在视图层,完全不侵入模型层代码。
修改后的完整代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class BoxAdapterToRenderer {
    // 类型映射表,key为Box实现类的Class对象,value为对应类型的渲染构造函数
    private static final Map<Class<? extends Box>, Function<? extends Box, Node>> RENDERER_FACTORY_MAP = new HashMap<>();

    // 静态块初始化映射关系
    static {
        RENDERER_FACTORY_MAP.put(Fighter.class, (Function<Fighter, Node>) BoxAdapterToRenderer::createRenderer);
        RENDERER_FACTORY_MAP.put(Bomb.class, (Function<Bomb, Node>) BoxAdapterToRenderer::createRenderer);
        RENDERER_FACTORY_MAP.put(Mine.class, (Function<Mine, Node>) BoxAdapterToRenderer::createRenderer);
        RENDERER_FACTORY_MAP.put(StaminaPad.class, (Function<StaminaPad, Node>) BoxAdapterToRenderer::createRenderer);
    }

    // 新增入参为Box的公共调用入口
    public static Node createRenderer(Box box) {
        Function<Box, Node> factory = (Function<Box, Node>) RENDERER_FACTORY_MAP.get(box.getClass());
        if (factory == null) {
            // 可按需处理未知Box类型的兜底逻辑,比如返回默认占位节点
            throw new IllegalArgumentException("无对应渲染逻辑的Box类型: " + box.getClass().getName());
        }
        return factory.apply(box);
    }

    // 原有各类型的重载方法保持不变
    public static Node createRenderer(Fighter fighter){
        Rectangle fighterRenderer = new Rectangle();
        fighterRenderer.setHeight(50);
        fighterRenderer.setWidth(50);
        Image im = new Image(Constants.ruleReader.getFighterImageURL(fighter.getName()),false);
        fighterRenderer.setFill(new ImagePattern(im));
        return fighterRenderer;
    }

    public static Node createRenderer(Bomb bomb){
        Rectangle bombRenderer = new Rectangle();
        bombRenderer.setHeight(50);
        bombRenderer.setWidth(50);
        Image im = new Image(Constants.ruleReader.getBombImageURL(),false);
        bombRenderer.setFill(new ImagePattern(im));
        return bombRenderer;
    }

    public static Node createRenderer(Mine mine){
        Rectangle mineRenderer = new Rectangle();
        mineRenderer.setHeight(50);
        mineRenderer.setWidth(50);
        Image im = new Image(Constants.ruleReader.getMineImageURL(),false);
        mineRenderer.setFill(new ImagePattern(im));
        return mineRenderer;
    }

    public static Node createRenderer(StaminaPad staminaPad){
        Rectangle staminaPadRenderer = new Rectangle();
        staminaPadRenderer.setHeight(50);
        staminaPadRenderer.setWidth(50);
        Image im = new Image(Constants.ruleReader.getStaminaPadImageURL(),false);
        staminaPadRenderer.setFill(new ImagePattern(im));
        return staminaPadRenderer;
    }
}

方案优势

  • 完全符合MVC分层约束,所有视图相关逻辑都在视图层,模型层代码无任何修改
  • 没有链式instanceof判断,运行时查找效率为O(1)
  • 后续新增Box实现类时,只需要新增对应重载方法、在静态块中加一行映射配置即可,符合开闭原则
  • 调用方式和你期望的完全一致,无需修改现有调用代码:
Box box = board.getGrid()[i][j];
Node renderer = BoxAdapterToRenderer.createRenderer(box);

内容的提问来源于stack exchange,提问作者Mattéo Da silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 18:54:00