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

仅统计常量名不同的接口实现类的优化设计模式推荐

优化方案:消除重复代码的两种实现方式

针对你遇到的两个实现类逻辑重复、仅统计指标名不同的问题,可以通过抽取公共逻辑+注入可变参数的方式彻底消除重复代码,以下是两种实用方案:

方案1:抽象基类复用核心逻辑

定义抽象基类封装所有公共逻辑,子类仅需提供对应的统计指标名,适合未来可能需要扩展子类独有逻辑的场景:

public interface OldIdResolver {
    // 修正接口方法参数,与实现类保持一致(原代码存在接口与实现方法不匹配的问题)
    Optional<String> getNewIdFromOldId(String oldId);
}

// 抽象基类封装公共逻辑
public abstract class AbstractOldIdResolver implements OldIdResolver {
    protected final IdService idService;
    protected final StatsDClient statsDClient;

    // 构造注入依赖
    public AbstractOldIdResolver(IdService idService, StatsDClient statsDClient) {
        this.idService = idService;
        this.statsDClient = statsDClient;
    }

    // 子类需实现该方法,返回对应统计指标名
    protected abstract String getMetricName();

    @Override
    public Optional<String> getNewIdFromOldId(String oldId) {
        Optional<Id> newIdOptional = idService.getNewIdFromOldId(oldId);
        if (newIdOptional.isPresent()) {
            statsDClient.incrementCounter(getMetricName());
        }
        return newIdOptional.map(Id::getValue); // 假设Id类有getValue方法转换为String
    }
}

// 自定义字段解析器:仅提供指标名
public class CustomFieldIdResolver extends AbstractOldIdResolver {
    public CustomFieldIdResolver(IdService idService, StatsDClient statsDClient) {
        super(idService, statsDClient);
    }

    @Override
    protected String getMetricName() {
        return "customField.oldIdUsed";
    }
}

// 搜索器解析器:仅提供指标名
public class SearcherIdResolver extends AbstractOldIdResolver {
    public SearcherIdResolver(IdService idService, StatsDClient statsDClient) {
        super(idService, statsDClient);
    }

    @Override
    protected String getMetricName() {
        return "searcher.oldIdUsed";
    }
}

方案2:通用实现类+构造注入指标名

如果不需要保留子类结构,可直接创建通用实现类,通过构造函数传入指标名,实现更轻量化的复用:

public interface OldIdResolver {
    Optional<String> getNewIdFromOldId(String oldId);
}

// 通用实现类,指标名通过构造注入
public class GenericOldIdResolver implements OldIdResolver {
    private final IdService idService;
    private final StatsDClient statsDClient;
    private final String metricName;

    public GenericOldIdResolver(IdService idService, StatsDClient statsDClient, String metricName) {
        this.idService = idService;
        this.statsDClient = statsDClient;
        this.metricName = metricName;
    }

    @Override
    public Optional<String> getNewIdFromOldId(String oldId) {
        Optional<Id> newIdOptional = idService.getNewIdFromOldId(oldId);
        if (newIdOptional.isPresent()) {
            statsDClient.incrementCounter(metricName);
        }
        return newIdOptional.map(Id::getValue);
    }
}

// 使用时直接创建实例
OldIdResolver customFieldResolver = new GenericOldIdResolver(idService, statsDClient, "customField.oldIdUsed");
OldIdResolver searcherResolver = new GenericOldIdResolver(idService, statsDClient, "searcher.oldIdUsed");

补充说明

  • 原代码中接口方法getNewIdFromOldId()无参数,但实现类方法带有String oldId参数,属于接口与实现不匹配的问题,已在方案中修正以保证代码可编译。
  • 两种方案均彻底消除了重复逻辑,方案1适合后续可能扩展子类功能的场景,方案2更简洁,适合仅指标名不同的简单场景。

内容的提问来源于stack exchange,提问作者Clare Phelps

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 11:03:24