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

使用结构型设计模式重构for-in循环与变量声明的冗余类型校验代码

解决方案

核心思路是将固定的校验流程与可变的校验规则、错误提示分离,通过组合而非继承的方式复用公共逻辑,具体实现步骤如下:

第一步:封装差异点为独立接口

首先定义函数式接口,用于承载不同场景下的校验规则和错误生成逻辑:

@FunctionalInterface
public interface TypeCompatibilityRule {
    // 校验类型是否兼容,兼容返回null,不兼容返回对应错误提示
    String getIncompatibleError(String leftHandSideType, String rightHandSideType);
}

同时定义错误上报的公共接口,统一不同Analyzer的错误提交能力:

public interface ErrorReporter {
    void addError(Token token, String message);
}

第二步:抽取公共校验逻辑到独立工具类

把两段代码里重复的空值判断、流程控制逻辑收拢到公共工具类,所有Analyzer都可以复用:

public class TypeCheckHelper {
    public static void verifyCompatibility(Token token, String leftType, String rightType,
                                           TypeCompatibilityRule rule, ErrorReporter reporter) {
        // 公共空判断逻辑
        if (leftType == null || rightType == null) {
            return;
        }
        // 调用传入的自定义校验规则
        String errorMsg = rule.getIncompatibleError(leftType, rightType);
        if (errorMsg != null) {
            reporter.addError(token, errorMsg);
        }
    }
}

第三步:改造原有Analyzer类

两个Analyzer分别实现ErrorReporter接口(原有addError方法不用修改,直接声明实现即可),声明各自的校验规则,调用公共工具类完成校验:

LoopAnalyzer改造后代码

// LoopAnalyzer.java
public class LoopAnalyzer implements ErrorReporter {
    // for-in循环专属校验规则
    private static final TypeCompatibilityRule FOR_IN_CHECK_RULE = (leftType, rightType) -> {
        if (!TypeUtils.isArrayType(leftType, rightType)) {
            return String.format("Types are not compatible, cannot check containment of %s in %s.", leftType, rightType);
        }
        return null;
    };

    @Override
    public void exitForInLoop(ForInLoopContext ctx) {
        final String rightHandSideType = this.determineExpressionReturnType(ctx.statementExpression());
        TypeCheckHelper.verifyCompatibility(ctx.start, ctx.solType().getText(), rightHandSideType,
                FOR_IN_CHECK_RULE, this);
    }

    // 原有addError方法无需修改,天然满足ErrorReporter接口要求
    @Override
    public void addError(Token token, String message) {
        // 原有错误上报逻辑
    }
}

ExpressionStatementAnalyzer改造后代码

// ExpressionStatementAnalyzer.java
public class ExpressionStatementAnalyzer implements ErrorReporter {
    // 变量赋值专属校验规则
    private static final TypeCompatibilityRule ASSIGNMENT_CHECK_RULE = (leftType, rightType) -> {
        if (!TypeUtils.areCompatible(leftType, rightType)) {
            return String.format("Cannot assign a %s value to a %s variable.", rightType, leftType);
        }
        return null;
    };

    @Override
    public void exitVariableDeclarationStatement(VariableDeclarationStatementContext ctx) {
        final String rightHandSideType = this.determineExpressionReturnType(ctx.statementExpression());
        TypeCheckHelper.verifyCompatibility(ctx.start, ctx.solType().getText(), rightHandSideType,
                ASSIGNMENT_CHECK_RULE, this);
    }

    // 原有addError方法无需修改
    @Override
    public void addError(Token token, String message) {
        // 原有错误上报逻辑
    }
}

方案优势

  • 完全消除了重复的流程代码,后续公共逻辑迭代只需要修改TypeCheckHelper一处
  • 没有破坏两个Analyzer的职责边界,避免了不合理的继承关系,符合组合优于继承的设计原则
  • 扩展性强,后续新增其他类型校验场景,只需要新增对应TypeCompatibilityRule实现即可,无需修改现有代码

内容的提问来源于stack exchange,提问作者N. Y. Wirawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 04:51:00