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

适配不同输入参数数量算法的最优设计模式选型

嘿,这个场景我太有共鸣了——碰到两个几乎一模一样的算法,就差参数多了个纬度,硬套模板模式非要传个带null纬度的对象,确实别扭得很。这里有几个更清爽的解决思路,你可以试试看:

方案1:用组合模式替代抽象模板类

别纠结抽象类的模板结构了,把90%的重复逻辑抽成一个独立的工具类,让两个算法类直接依赖它,各自处理自己的参数适配就行。这样既保留了代码复用,又不会出现多余的null参数。

先写公共核心逻辑:

public class CommonAlgorithmLogic {
    // 第一个算法用的核心计算逻辑
    public double coreCalculate(double longitude) {
        // 这里放两个算法90%重复的计算代码
        return longitude * 1.2; // 示例逻辑
    }

    // 第二个算法用的重载版本,在通用逻辑基础上加纬度处理
    public double coreCalculate(double longitude, double latitude) {
        double baseResult = coreCalculate(longitude);
        // 这里加第二个算法特有的纬度相关计算
        return baseResult + (latitude * 0.8);
    }

    // 两个算法共用的保存逻辑
    public void coreSave(double result, String algorithmType) {
        // 通用保存代码,比如写入数据库、日志等
        System.out.println("Saving result for " + algorithmType + ": " + result);
    }
}

然后第一个算法类(只需要经度):

public class LongitudeOnlyAlgorithm {
    private final CommonAlgorithmLogic commonLogic = new CommonAlgorithmLogic();

    public void run(double longitude) {
        double result = commonLogic.coreCalculate(longitude);
        commonLogic.coreSave(result, "longitude-only");
    }
}

第二个算法类(需要经纬度):

public class LongLatAlgorithm {
    private final CommonAlgorithmLogic commonLogic = new CommonAlgorithmLogic();

    public void run(double longitude, double latitude) {
        double result = commonLogic.coreCalculate(longitude, latitude);
        commonLogic.coreSave(result, "long-lat");
    }
}

调用的时候直接传各自需要的参数就行,干净利落,完全不用处理null。

方案2:函数式接口+默认方法(Java 8+)

如果还是想保留“定义执行流程”的模板特性,可以用接口的默认方法来封装通用流程,同时用重载或默认方法处理参数差异:

public interface Algorithm {
    // 封装通用执行流程:计算→保存
    default void execute(double longitude) {
        double result = calculate(longitude);
        save(result);
    }

    // 给第二个算法重载的执行方法
    default void execute(double longitude, double latitude) {
        double result = calculate(longitude, latitude);
        save(result);
    }

    // 基础计算逻辑(两个算法共用的90%代码)
    double calculate(double longitude);

    // 带纬度的计算,默认实现调用基础逻辑+空扩展,第一个算法不用管
    default double calculate(double longitude, double latitude) {
        return calculate(longitude);
    }

    // 通用保存逻辑
    default void save(double result) {
        // 共用的保存代码
        System.out.println("Saving result: " + result);
    }
}

第一个算法实现:

public class LongitudeOnlyAlgorithm implements Algorithm {
    @Override
    public double calculate(double longitude) {
        // 核心计算逻辑
        return longitude * 1.2;
    }
}

第二个算法只需要扩展纬度相关的计算:

public class LongLatAlgorithm implements Algorithm {
    @Override
    public double calculate(double longitude) {
        // 和第一个算法完全一样的核心逻辑
        return longitude * 1.2;
    }

    @Override
    public double calculate(double longitude, double latitude) {
        // 在核心逻辑基础上加纬度处理
        double baseResult = super.calculate(longitude);
        return baseResult + (latitude * 0.8);
    }
}

这个方案既保留了模板模式的流程封装,又让每个算法只处理自己需要的参数,没有多余的null。

方案3:Builder模式封装参数(适合参数可能扩展的场景)

如果以后还可能加更多参数(比如海拔、时间戳),用Builder模式封装参数是个更健壮的选择,既能保证必要参数不缺失,又能让每个算法只取自己需要的参数:

先定义参数Builder:

public class AlgorithmParams {
    private final double longitude;
    private Double latitude;

    private AlgorithmParams(Builder builder) {
        this.longitude = builder.longitude;
        this.latitude = builder.latitude;
    }

    public static class Builder {
        private double longitude;
        private Double latitude;

        public Builder longitude(double longitude) {
            this.longitude = longitude;
            return this;
        }

        public Builder latitude(double latitude) {
            this.latitude = latitude;
            return this;
        }

        public AlgorithmParams build() {
            // 校验必要参数,比如经度必须传
            return new AlgorithmParams(this);
        }
    }

    // Getter方法
    public double getLongitude() { return longitude; }
    public Double getLatitude() { return latitude; }
}

然后调整模板类,用这个参数对象:

public abstract class AlgorithmTemplate {
    public final void execute(AlgorithmParams params) {
        double result = calculate(params);
        save(result);
    }

    protected abstract double calculate(AlgorithmParams params);

    protected void save(double result) {
        // 通用保存逻辑
        System.out.println("Saving result: " + result);
    }
}

第一个算法实现:

public class LongitudeOnlyAlgorithm extends AlgorithmTemplate {
    @Override
    protected double calculate(AlgorithmParams params) {
        // 只用到经度,完全不用管纬度
        return params.getLongitude() * 1.2;
    }
}

第二个算法实现:

public class LongLatAlgorithm extends AlgorithmTemplate {
    @Override
    protected double calculate(AlgorithmParams params) {
        double baseResult = params.getLongitude() * 1.2;
        // 用到纬度,这里可以放心用,因为调用时会传
        return baseResult + (params.getLatitude() * 0.8);
    }
}

调用的时候:

// 第一个算法只传经度
new LongitudeOnlyAlgorithm().execute(new AlgorithmParams.Builder().longitude(120.0).build());
// 第二个算法传经纬度
new LongLatAlgorithm().execute(new AlgorithmParams.Builder().longitude(120.0).latitude(30.0).build());

这个方案的好处是参数扩展灵活,而且不会出现不必要的null,因为Builder可以控制哪些参数是可选的。


内容的提问来源于stack exchange,提问作者Aleksander Monk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:50:41