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

如何践行单一职责原则?三种实现方式及DI与接口的作用

单一职责原则(SRP)实现方案分析与DI/接口的角色

三种实现方式的对比与最佳选择

我们逐个分析你给出的三种实现方式:

1. 静态方法(Approach2)

  • 优势:实现极简,不需要实例化对象,适合无状态的纯逻辑场景(比如你这个固定乘10的计算),调用成本低。
  • 劣势:扩展性差,无法通过依赖注入替换逻辑;测试时难以模拟,只能硬编码逻辑;如果后续需要给计算逻辑加状态(比如缓存计算结果),完全无法适配。

2. 实例化类(Approach1)

  • 优势:符合面向对象封装思想,类可以持有状态(当前例子没用到,但后续扩展可用);支持依赖注入,方便测试和扩展(比如继承该类修改计算逻辑);职责单一,SingleResponsabiltyApproach1只负责乘10的计算,和Factoriser完全解耦。
  • 劣势:每次使用需要实例化对象,但C#中这种轻量对象的实例化开销几乎可以忽略,完全不用纠结。

3. 传递完整父类(Approach3)

  • 核心问题:严重违反单一职责原则,SingleResponsabiltyApproach3直接依赖Factoriser的完整实例,导致两个类耦合度极高——Factoriser的任何字段修改、逻辑变更都可能影响这个类,完全违背了拆分臃肿类、降低耦合的初衷。
  • 内存疑问:在C#中,引用类型参数传递的是引用(指针),不会复制整个对象,内存开销极小,但这不是重点,重点是这种设计的耦合问题必须避免。

最佳选择:如果当前场景只是简单的无状态计算,静态方法可以用,但从长期扩展性和代码可维护性考虑,实例化类(Approach1)是最优方案。绝对要避免Approach3的写法。

依赖注入(DI)与接口的角色

接口的作用

接口是落地SRP和开闭原则的核心工具:

  • 定义抽象契约:比如定义IFactorCalculator接口,约定Calculate(int value)方法,让计算类实现这个接口。这样Factoriser只依赖抽象接口,不依赖具体的计算实现。
  • 解耦依赖:当需要修改计算逻辑(比如改成乘20),只需要新增一个实现IFactorCalculator的类,不需要修改Factoriser的代码,完全符合“对扩展开放,对修改关闭”的原则。

依赖注入(DI)的作用

  • 消除硬编码实例化:Factoriser不需要自己new计算类实例,而是通过构造函数或方法参数接收IFactorCalculator的实例,由外部(比如DI容器)负责创建和注入。
  • 提升可测试性:测试时可以注入一个模拟的IFactorCalculator实现,验证Factoriser的逻辑是否正确,不需要依赖真实的计算逻辑。
  • 增强灵活性:可以根据不同场景切换计算实现(比如生产环境用普通计算,测试环境用模拟计算)。

优化后的代码示例

namespace SingleResponsabilityTest
{
    // 定义抽象接口,约定计算契约
    internal interface IFactorCalculator
    {
        int Calculate(int value);
    }

    // 具体计算类,只负责乘10的逻辑,符合SRP
    internal class TenFactorCalculator : IFactorCalculator
    {
        public int Calculate(int value)
        {
            return value * 10;
        }
    }

    // Factoriser只负责业务逻辑,依赖抽象接口,不耦合具体实现
    internal class Factoriser
    {
        private readonly IFactorCalculator _calculator;
        public int classSpecificInt = 10;

        // 构造函数注入依赖
        public Factoriser(IFactorCalculator calculator)
        {
            _calculator = calculator;
        }

        public void DoFactorTen()
        {
            Console.WriteLine(_calculator.Calculate(classSpecificInt));
            Console.ReadLine();
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            // 实际项目中可由DI容器管理实例,这里手动示例
            IFactorCalculator calculator = new TenFactorCalculator();
            Factoriser factoriser = new Factoriser(calculator);
            factoriser.DoFactorTen();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:55:17