仅统计常量名不同的接口实现类的优化设计模式推荐
优化方案:消除重复代码的两种实现方式
针对你遇到的两个实现类逻辑重复、仅统计指标名不同的问题,可以通过抽取公共逻辑+注入可变参数的方式彻底消除重复代码,以下是两种实用方案:
方案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
相关产品推荐
相关产品推荐

