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

违反SOLID原则的C# Calculator类重构方案咨询

代码问题判定

你判断的没错,这段代码首先违反单一职责原则,同时还违反了开闭原则、依赖倒置原则,存在硬编码字符串易出错、可扩展性差的问题:

  • 单一职责违反点:Calculator类同时承担了运算逻辑实现、运算类型匹配分发两个职责,加减乘除任意一个运算规则修改,都需要改动整个Calculator类的代码,很容易引入牵连bug
  • 开闭原则违反点:新增运算(比如取模、幂运算)必须修改Calculate方法的if-else分支,侵入已稳定的原有代码
  • 健壮性缺陷:硬编码字符串做分支判断很容易出现拼写错误,比如你贴的代码里除法的标识写的是"devide"(正确拼写为divide),会直接导致除法调用失败;也没有做除数为0的校验、不支持运算的异常提示
重构方案

核心思路是抽象运算公共契约,拆分每个运算为独立实现类,让计算器类仅依赖抽象做请求分发,完全贴合SOLID要求:

  1. 首先定义运算的抽象接口,统一所有运算的行为规范
  2. 把加减乘除每种运算拆成独立的类,每个类只实现自己对应的运算逻辑
  3. 重构计算器类,依赖抽象接口完成运算注册和分发,不再耦合具体运算逻辑

重构后代码实现

/// <summary>
/// 运算抽象契约,所有可支持的运算都需实现该接口
/// </summary>
public interface IOperation
{
    /// <summary>
    /// 运算类型唯一标识
    /// </summary>
    string OperationCode { get; }
    /// <summary>
    /// 执行具体运算逻辑
    /// </summary>
    int Calculate(int a, int b);
}

// 加法实现
public class AddOperation : IOperation
{
    public string OperationCode => "add";
    public int Calculate(int a, int b) => a + b;
}

// 减法实现
public class SubtractOperation : IOperation
{
    public string OperationCode => "subtract";
    public int Calculate(int a, int b) => a - b;
}

// 乘法实现
public class MultiplyOperation : IOperation
{
    public string OperationCode => "multiply";
    public int Calculate(int a, int b) => a * b;
}

// 除法实现(修正原代码拼写问题,增加参数合法性校验)
public class DivideOperation : IOperation
{
    public string OperationCode => "divide";
    public int Calculate(int a, int b)
    {
        if (b == 0) throw new DivideByZeroException("除数不能为0");
        return a / b;
    }
}

/// <summary>
/// 重构后的计算器类
/// </summary>
public class Calculator
{
    private readonly Dictionary<string, IOperation> _operationMap;

    /// <summary>
    /// 构造函数注入所有需要支持的运算实例
    /// </summary>
    /// <param name="operations">所有支持的运算实现集合</param>
    public Calculator(IEnumerable<IOperation> operations)
    {
        // 初始化时构建运算标识和实例的映射关系,忽略大小写匹配
        _operationMap = operations.ToDictionary(
            op => op.OperationCode, 
            StringComparer.OrdinalIgnoreCase);
    }

    public int Calculate(int a, int b, string operation)
    {
        if (!_operationMap.TryGetValue(operation, out var targetOperation))
        {
            throw new NotSupportedException($"不支持的运算类型:{operation}");
        }
        return targetOperation.Calculate(a, b);
    }
}

调用示例

// 初始化计算器,注入需要支持的运算
var calculator = new Calculator(new List<IOperation>
{
    new AddOperation(),
    new SubtractOperation(),
    new MultiplyOperation(),
    new DivideOperation()
});

// 执行计算
int sum = calculator.Calculate(3, 5, "add"); // 返回8
int product = calculator.Calculate(4, 6, "multiply"); // 返回24
int quotient = calculator.Calculate(10, 2, "divide"); // 返回5
重构后对SOLID的符合说明
  • 单一职责原则:每个具体运算类只负责自身的运算逻辑实现,Calculator类仅负责运算注册、请求匹配分发,不同职责完全拆分,修改某一个运算逻辑不会影响其他模块
  • 开闭原则:后续新增运算类型时,只需要新增一个实现IOperation接口的类,初始化计算器时注入即可,完全不需要修改Calculator类的原有代码,对扩展开放、对修改关闭
  • 里氏替换原则:所有IOperation的实现类都可以互相替换,不会导致计算器运行异常
  • 接口隔离原则:IOperation接口仅定义运算必需的两个成员,没有冗余方法,所有实现类不需要依赖自己不需要的接口定义
  • 依赖倒置原则:计算器类依赖抽象的IOperation接口,不依赖加减乘除的具体实现,高层模块和低层模块都基于抽象耦合

内容的提问来源于stack exchange,提问作者Jafar ashrafi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 02:46:12