如何重构接口的两类存在细微差异的实现以消除重复代码?
重构相似接口实现:提取重复代码的实用方案
嘿,这个场景我碰到过好多次!当两个类实现同一个接口,Evaluate方法大部分逻辑重合但又有细微差异时,咱们可以用几种经典的重构手法来消除重复,同时还能保留各自的独特逻辑。下面给你拆解几个好用的方案:
1. 模板方法模式(Template Method Pattern)—— 适合固定流程下的差异步骤
这是处理这类问题最常用的方案之一。核心思路是:把通用的流程逻辑抽到一个抽象基类里,同时把有差异的部分定义成抽象方法(或者可重写的钩子方法),让子类去实现这些差异化逻辑。
举个例子:
假设你的接口是IEvaluator,两个实现类是UserEvaluator和OrderEvaluator,它们的Evaluate都要做参数校验、数据加载,然后计算结果,只是计算结果的逻辑不一样。
首先定义抽象基类:
public abstract class BaseEvaluator : IEvaluator { public bool Evaluate(InputData data) { // 通用步骤1:参数校验 if (!ValidateInput(data)) { return false; } // 通用步骤2:加载关联数据 var relatedData = LoadRelatedData(data); // 差异化步骤:交给子类实现 return CalculateResult(data, relatedData); } // 通用方法,子类可以直接用 private bool ValidateInput(InputData data) { // 通用校验逻辑 return data != null && !string.IsNullOrEmpty(data.Id); } private RelatedData LoadRelatedData(InputData data) { // 通用数据加载逻辑 return DataProvider.Get(data.Id); } // 抽象方法,子类必须实现的差异化逻辑 protected abstract bool CalculateResult(InputData data, RelatedData relatedData); }
然后两个子类只需要实现差异化的部分:
public class UserEvaluator : BaseEvaluator { protected override bool CalculateResult(InputData data, RelatedData relatedData) { // User专属的计算逻辑 return relatedData.UserScore > 80; } } public class OrderEvaluator : BaseEvaluator { protected override bool CalculateResult(InputData data, RelatedData relatedData) { // Order专属的计算逻辑 return relatedData.OrderAmount > 1000; } }
说白了,就是把固定的流程“模板”定好,可变的部分留口子给子类填。
2. 策略模式(Strategy Pattern)—— 适合可替换的差异化算法
如果你的差异化逻辑是独立的算法片段,而且未来可能还要加新的实现,那策略模式会更灵活。核心是把差异逻辑封装成独立的策略类,然后让原来的两个实现类依赖不同的策略。
比如:
先定义策略接口:
public interface IEvaluationStrategy { bool CalculateResult(InputData data, RelatedData relatedData); } // 两个策略实现 public class UserEvaluationStrategy : IEvaluationStrategy { public bool CalculateResult(InputData data, RelatedData relatedData) { return relatedData.UserScore > 80; } } public class OrderEvaluationStrategy : IEvaluationStrategy { public bool CalculateResult(InputData data, RelatedData relatedData) { return relatedData.OrderAmount > 1000; } }
然后原来的实现类改成依赖策略:
public class UserEvaluator : IEvaluator { private readonly IEvaluationStrategy _strategy; public UserEvaluator() { _strategy = new UserEvaluationStrategy(); } public bool Evaluate(InputData data) { // 通用逻辑和之前一样 if (!ValidateInput(data)) return false; var relatedData = LoadRelatedData(data); // 调用策略处理差异 return _strategy.CalculateResult(data, relatedData); } // 通用方法可以抽到工具类里,这里简化演示 private bool ValidateInput(InputData data) { /* ... */ } private RelatedData LoadRelatedData(InputData data) { /* ... */ } }
这种方式的好处是,差异化逻辑和主逻辑解耦了,以后加新的Evaluator,只需要加新的策略类就行,不用改原来的代码。
3. 提取工具类/通用方法—— 适合差异极小的场景
如果两个类的Evaluate只有几行代码不一样,那没必要搞复杂的设计模式,直接把通用逻辑抽到一个静态工具类或者辅助类里就行。
比如:
public static class EvaluationUtils { public static bool ExecuteCommonSteps(InputData data, out RelatedData relatedData) { relatedData = null; if (!ValidateInput(data)) { return false; } relatedData = LoadRelatedData(data); return true; } private static bool ValidateInput(InputData data) { /* ... */ } private static RelatedData LoadRelatedData(InputData data) { /* ... */ } }
然后子类里调用:
public class UserEvaluator : IEvaluator { public bool Evaluate(InputData data) { if (!EvaluationUtils.ExecuteCommonSteps(data, out var relatedData)) { return false; } // 自己的差异逻辑 return relatedData.UserScore > 80; } }
这种方式最简单直接,适合差异很小的情况,不用引入额外的类层次。
怎么选?
- 如果是固定流程里有几个步骤不同:选模板方法模式,代码结构最清晰。
- 如果是差异化逻辑是可替换的算法,且未来可能扩展:选策略模式,灵活性更高。
- 如果只是几行代码的差异:直接抽工具类,快速解决问题。
内容的提问来源于stack exchange,提问作者Siva Vaddadi
相关产品推荐
相关产品推荐

